如图这是async的eachOf方法官方文档以及demo,我是个小白,研究了挺久没看懂,我的问题是:
这里iteratee异步函数的三个参数里,最后的callback(如图所示)是什么时候被调用?
照我的理解是循环一次调用一次,但显然不是这样。
PS:demo的运行结果是输出三个文件的所有内容的一个{}。
求大神指点
循环一次调用一次,正常情况下调用的次数等于obj键的个数。
@zhongshiji 另外你用错了,应该是async.eachOf
@lovegnep 这个是别名,两个名字都可以用,是官网demo
@lovegnep 请帮我看下这个
为了测试一下这个callback,运行结果没有按理想的输出一个数组,这是为什么呢?
@zhongshiji 哦,献丑了
@zhongshiji 输出结果是啥呢?报错了?
来自酷炫的 CNodeMD
@lovegnep 没有报错,输出了20项“写入成功",但是字符1跟arr没有输出。(有两项没爬取到请忽略)
@lovegnep 如果将arr.push(key)与callback()两句往下放在下面err = > {}的正上面(如下图),倒是能正常输出arr数组与“写入成功”,但是为何不能像截图一样放在fs.writeFile()里面,这是我不能理解的。(官网demo中callback()也是放在fs.readFile()里面)
@zhongshiji articleurl的长度是多少呢,如果callback的调用次数不等于长度,那么是不会走到最后的打印1和数组的。writefile发生错误不要返回,把return去掉
来自酷炫的 CNodeMD
eachOf(coll, iteratee, callbackopt) iteratee的第三个参数callback在每次执行iteratee中一定要运行到,即如果iteratee中发生错误则调用callback(err),否则callback(null)
另外建议你不要贴图片,想改下你的代码没法复制呀
async.eachOf(articleUrls,function (value, key, callback) {
request(value, function (error, response, body) {
if (!error && response.statusCode === 200) {
const $ = cheerio.load(body)
fs.writeFile(path.join(__dirname, `./教务处公告/${key}` + '.txt'), $('h1').text() + $('#content p').text(), function(err) {
if (err) {
return callback(err)
}
try {
arr.push(key)
console.log(`第${ key + 1 }项`, '写入成功')
} catch (e) {
return callback(e)
}
callback()
})
}
})
}, err => {
if (err) {
console.error(err.message)
}
console.log('1', arr)
})
@lovegnep 改成了这样,也是不行。没输出数组,去掉return也是一样。
@lovegnep articleUrls的长度为20,因为有两条我的规则没涵盖到,只抓取到18条。
@lovegnep 我大概抓住了一点重点,通过fs.writeFile本地只生成了18个txt文件,但应该是生成20个,问题出在哪儿了?,而且少掉的两个刚好是因为
fs.writeFile(file, data[, options], callback)
中data为空的那两个。
如果下面这样还不行的话我也不知道为啥了
async.eachOf(articleUrls,function (value, key, callback) {
request(value, function (error, response, body) {
if (!error && response.statusCode === 200) {
const $ = cheerio.load(body)
fs.writeFile(path.join(__dirname, `./教务处公告/${key}` + '.txt'), $('h1').text() + $('#content p').text(), function(err) {
if (err) {
return callback(err)
}
try {
arr.push(key)
console.log(`第${ key + 1 }项`, '写入成功')
} catch (e) {
return callback(e)
}
callback()
})
}else{
callback(err)
}
})
}, err => {
if (err) {
console.error(err.message)
}
console.log('1', arr)
})
@zhongshiji l加个else判断下
if (!error && response.statusCode === 200)esle{....}
@lovegnep 你这样我运行了下,在else{}中callback(err)报错: err is not defined.
@lovegnep 您之前说“iteratee的第三个参数callback在每次执行iteratee中一定要运行到”,但是我iteratee中
fs.writeFile(file, data[, options], callback)
有两个data为空,由key并未生成那两个.txt文件,是不是因为这个,callback有两次没有运行到呢?
@zhongshiji 是的,用下面这样就行了
async.eachOf(articleUrls,function (value, key, callback) {
request(value, function (error, response, body) {
if (!error && response.statusCode === 200) {
const $ = cheerio.load(body)
fs.writeFile(path.join(__dirname, `./教务处公告/${key}` + '.txt'), $('h1').text() + $('#content p').text(), function(err) {
if (err) {
return callback(err)
}
try {
arr.push(key)
console.log(`第${ key + 1 }项`, '写入成功')
} catch (e) {
return callback(e)
}
callback()
})
}else{
callback('请求出错')
}
})
}, err => {
if (err) {
console.error(err.message)
}
console.log('1', arr)
})
@lovegnep 问题解决,最后是这样:
async.eachOf(articleUrls, function(value, key, callback) {
request(value, function(error, response, body) {
if (!error && response.statusCode === 200) {
const $ = cheerio.load(body)
fs.writeFile(path.join(__dirname, `./教务处公告/${key}` + '.txt'), $('h1').text() + $('#content p').text(), function(err) {
if (err) {
return callback(err)
}
try {
arr.push(key)
console.log(`第${ key + 1 }项`, '写入成功')
} catch (e) {
return callback(e)
}
callback()
})
} else {
callback(error)
}
})
}, err => {
if (err) {
console.error(err.message)
}
console.log('1', arr)
})
else中callback参数是error,不是err,也正如您所说。结果是这样:
@lovegnep 非常感谢!我对callback()的理解又深了一点,最后再请问一下,async.eachOf()的iteratee第三个参数callback是不是循环一次调用一次,在callback的次数==articleUrls.length的时候,async.eachOf()的第三个参数callback才被触发?
是的,请看官方文档:
A callback which is called when all iteratee functions have finished, or an error occurs. Invoked with (err).
@lovegnep 受教了。