nodejs对异步的实现非常彻底,接触时间不久,写爬虫的时候按照以往的思路将request的结果直接赋值给全局变量,结果发现没有输出,对此很困惑,经过查询发现如下
看下面的片段,输出为空
fs.readFile
是异步读取,log函数输出是getDate()
还没有获取到数据
const fs = require('fs')
function getData(){
fs.readFile('demo.txt',(err,data) => { //异步事件
return data;
})
}
console.log(getData())
再看看promise实现,log函数仍旧没有输出,和回调函数的问题一样
const fs = require('fs')
function getData(){
fs.promises.readFile("demo.txt")
.then(function(result) {
return result
})
.catch(function(error) {
console.log(error);
})
}
console.log(getData())
所以,要想获取异步逻辑的数据,就只能等待异步函数执行完毕得到数据之后在获取,需要延迟获得自然想到了回调函数
全局log仍旧无法输出,意味着同步逻辑没有获得异步数据
const fs = require('fs')
data = ''
function getData(callback){
fs.promises.readFile("demo.txt")
.then(function(result) {
return result
})
}
getData(function(result){
console.log(result)
data = result
})
console.log(data)
再来看看promise
利用回调函数无效
直接返回promise,表明该结果在未来才能获取,仍旧需要在同步代码中进行回调,显而易见回调仍旧无效
async实际上是promise的封装,结果也相同
const fs = require('fs')
data = ''
function getData(callback){
fs.promises.readFile("demo.txt")
.then(function(result) {
callback(result)
})
}
getData(function(result){
console.log(result)
data = result
})
console.log(data.toString())
//返回promise
data = ''
function getData(callback){
return fs.promises.readFile("demo.txt") .then((data)=>data)
}
getData().then((res)=>data=res)
console.log(data.toString())
//或者async
async function getData(callback){
return await fs.promises.readFile("demo.txt")
}
或者以订阅发布模式获取,仍旧无效(按理说是可以的)
var events = require('events');
var fs = require('fs')
var EventEmitter = new events.EventEmitter();
data = ''
function getData(){
fs.readFile('demo.txt',(err,data) => {
EventEmitter.emit('sendData',data)
})
}
getData()
EventEmitter.on('sendData',function(res){
data = res
})
console.log(data);
以上对nodejs简单的异步代码进行了回顾,可见同步代码和异步代码是两条不同的执行逻辑,之所以同步获取不到异步数据,是由于异步数据的获取时间未知,比起回调函数,强行获取也是不合逻辑的
来看看同步方式就完全没有问题
var fs = require('fs')
data = ''
function getData() {
return fs.readFileSync('demo.txt')
}
data = getData()
console.log(data.toString())
进一步思考,既然同步代码是因为不确定异步数据的时机,还没有获取到就执行完毕了,那让同步代码等待不就行了?
然而查找发现nodejs并没有sleep函数的实现,但是可以通过setTimeout
进行模拟,将同步逻辑包裹起来
setTimeout(() => {
data.toString())
}, 3000);
但是这…不还是进入了异步执行的逻辑么
所以最终结论是同步代码只能通过回调函数,实现同步异步逻辑交替执行的结果
最后如果确定异步逻辑获得了数据,如何强行取出?
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)