javascript - 功能代码未按正确顺序执行,异步等待执行错误
问题描述
我在端点中尝试做的是:
- 进行 API 调用,返回 JSON
- 对于每个项目:在我们的数据库中搜索它
- 如果找到,请跳过它。
- 如果未找到,将其推送到数组“响应”中
这是我的代码:
app.get("/test", (req,res) => {
spotifyApi.getUserPlaylists({ limit: 50 })
.then(function(data) {
let finalres = [];
const tbp = data.body.items;
// res.send('ok stop loading');
tbp.forEach(element => locateit(element,finalres));
console.log('This is the length of finalres, which should be 1:', finalres.length);
finalres.forEach(item =>{console.log(item)});
function locateit(item, finalres){
const thisplaylistid = item.id;
collection.find({ "id" : thisplaylistid }).toArray((error, result) => {
if(error) {
return res.status(500).send(error);
}
if(result.length == 0) { // if we don't find this playlist in our DB
console.log('This playlist is not in our database: ');
console.log(thisplaylistid);
finalres.push(thisplaylistid);
}
else{ //if it's already in our DB
console.log('This item is in our database.'); //This should be printed first, six times.
}
});
};
});
});
的内容data.body.items
是 7 项,其中只有前 6 项在我们的数据库中。这意味着,最后一项应该被推入finalres
。因此,预期的控制台结果应该是:
This item is in our database.
This item is in our database.
This item is in our database.
This item is in our database.
This item is in our database.
This playlist is not in our database:
3uDLmuYPeRUxXouxuTsWOe
This is the length of finalres, which should be 1: 1
3uDLmuYPeRUxXouxuTsWOe
但相反,我得到了这个:
This is the length of finalres, which should be 1: 0
This should be displayed first, six times.
This should be displayed first, six times.
This should be displayed first, six times.
This should be displayed first, six times.
This should be displayed first, six times.
This should be displayed first, six times.
This playlist is not in our database:
3uDLmuYPeRUxXouxuTsWOe
它显然没有按正确的顺序执行。我尝试使用异步等待,但我很难理解应该在哪里/如何实现它。有什么帮助吗?这是我尝试过的部分,但我得到了与以前相同的控制台结果:
async function locateit(item, finalres){
const thisplaylistid = item.id;
await collection.find({ "id" : thisplaylistid }).toArray((error, result) => {
...
更新
在阅读了有关 async-wait 和 promise 的更多信息后,我尝试这样做,但我仍然得到相同的输出。
app.get("/test", (req,res) => {
spotifyApi.getUserPlaylists({ limit: 50 })
.then(function(data) {
let finalres = [];
const tbp = data.body.items;
// res.send('ok stop loading');
for (const playlist of tbp) {
async function doWork() {
const found = await indb(playlist.id); //returns t/f if found or not found
if (!found){
finalres.push(playlist);
}
}
doWork();
}
console.log('This is the length of finalres and it should be 1: ',finalres.length);
})
});
indb 函数如下所示:
function indb(thisplaylistid){
return new Promise((resolve, reject) =>{
console.log('Searching in our DB...');
collection.find({ "id" : thisplaylistid }).toArray((error, result) => {
if(result.length == 0) { // if we don't find this playlist in our DB
console.log('This playlist is not in our database: ');
console.log(thisplaylistid);
resolve(false); //returns the id
}
else{ //if it's already in our DB
console.log('This item is in our database.'); //This should be printed first, six times.
resolve(true);
}
});
})
}
解决方案
这里的问题是,无论您是否有异步承诺在其中运行,forEach 解析总是解析为 void。
因此,您的代码将在执行 forEach 中的语句之前返回
正确的做法是使用#Promise.all等待所有承诺解决
试试这个:
按照 Bergi 的建议更新了使用 promise 而不是回调(更可取)
app.get("/test", (req, res) => {
spotifyApi.getUserPlaylists({ limit: 50 })
.then((data) => {
// :refac: more meaningful variable names
const playlists = data.body.items
return Promise.all(
playlists.map(
// :refac: destructuring to get only the id, other ain't necessary
async({ id }) =>
collection.find({ id }).toArray()
)
)
.then(playlistsById =>
// :refac: no error occurred fetching playlists
const nonEmptyPlaylists = playlistsById.filter(playlistById => playlistById.length !== 0)
res.status(200).send(nonEmptyPlaylists)
)
.catch(error => {
// :refac: some error occurred at searching some playlist
console.log('error', error)
// :refac: if you might expect that is going to throw an error here, the code shouldn't be 500
return res.status(400).send(error)
})
})
})
推荐阅读
- javascript - 如何在vue的表格行中制作左侧的徽章?
- mysql - 列计数与设置自动增量的行的值计数不匹配
- javascript - 在 PHP 中下载多个文件的最佳做法是什么?
- node.js - 在while循环完成后执行while循环中的条件语句
- python - 如何使用python发送超链接作为对对话流的响应?
- python - 如何测量离散小波变换 (DWT) 和复小波变换中的位移方差
- vb.net - 如何在 vb.net 中使用 linq 使用别名调用数据表列两次
- google-api - 从调用日历 api 看到 SocketTimeoutException 的高比率
- java - 父模块 pom.xml 中的依赖管理不起作用
- java - JSONObject.element() 方法将“null”字符串值转换为 null