Javascript 等待在reduce()函数中完成异步函数
我有一项职能,其中包括:Javascript 等待在reduce()函数中完成异步函数,javascript,asynchronous,es6-promise,reduce,npm-request,Javascript,Asynchronous,Es6 Promise,Reduce,Npm Request,我有一项职能,其中包括: const newThreads = newItems.reduce( (acc, item) => { request(item.href, function(error2, response2, html2){ if(!error2) { const thread = cheerio.load(html2) const today = thread('div#ignmsgbttns1').parent().parent(
const newThreads = newItems.reduce( (acc, item) => {
request(item.href, function(error2, response2, html2){
if(!error2) {
const thread = cheerio.load(html2)
const today = thread('div#ignmsgbttns1').parent().parent().find("b:contains('Today')")
if(today.text()) {
acc.push(item)
}
}
})
return acc
}, [])
console.log(newThreads)
当然,由于异步的原因,日志返回一个空数组
(request
)在reduce
循环中执行
所以我想做的是:
const newThreads = await newItems.reduce( etc...
然后等待reduce
循环中的请求完成
但我不知道如何正确地做这件事
所以我知道我必须使用async
、wait
或promissions
,但我不知道怎么做
我认为reduce回调
也必须是async
,但在这一点上绝对不能确定
request
方法来自,它们也提供了一些使用承诺,但老实说,我不知道如何将其应用于reduce
我很确定在某个地方已经有一个类似的问题,但是找不到
任何帮助都将不胜感激
ps:对于那些想知道cheerio是什么的人,这里是
应用答案后的最终代码
我不得不使用
为了使这项工作顺利进行,你需要
newThreads
变量将是通过条件检查的项目数组的承诺。Thx获取您的答案。在方法中,html2现在返回一个请求对象,但应该返回一个包含请求html的字符串。在记录新线程时,我也会得到“Promise{}”。我必须使用这些请求承诺包吗?@OlivierKrull您不能立即从异步函数返回结果字符串。等待承诺。必须对代码进行一些修改,但基本上这是正确的答案。我们真的不清楚为什么要使用reduce
。您不应该使用map
和可能的filter
构建结果吗?然后你可以简单地使用Promise.all
@Bergi据我所知map
返回一个与原始数组长度相等的数组,在我的情况下,我必须过滤掉一些项目。但你是对的,即使我的问题现在解决了,也许我会尝试一下过滤器。
const newThreads = newItems.reduce(async (acc, item) => {
const current = await acc;
const html2 = await requestAsync(item.href);
const thread = cheerio.load(html2.body);
const today = thread('div#ignmsgbttns1')
.parent()
.parent()
.find("b:contains('Today')");
if (today.text()) current.push(item);
return current;
}, []);
newThreads.then((res) => {
//..doing stuff with res
})
const newThreads = newItems.reduce(async (acc, item) => { // note async
const current = await acc; // unwrap the previous Promise
try {
const html2 = await request(item.href); // unwrap request Promise
const thread = cheerio.load(html2);
const today = thread('div#ignmsgbttns1')
.parent()
.parent()
.find("b:contains('Today')");
if (today.text()) current.push(item);
} catch (error2) {
// do whatever
}
return current;
}, []);