当我运行下面的代码块时,我总是得到错误-UnhandledPromiseRejectionWarning:UnhandledPromiseRejection。 此错误可能是由于不带catch块的异步函数内部引发的,或者是由于拒绝了未用。catch()处理的承诺。 要在未处理的承诺拒绝时终止节点进程,请使用CLI标志--unhandled-rejections=strict
(请参阅https://nodejs.org/api/CLI.html#CLI_unhandled_rejections_mode)。 (拒绝ID:1)
module.exports = (app, spotifyAPI) => {
app.get('/api/search', requireLogin, async (req, res) => {
const URI_BASE = keys.ComputerVisionEndpoint + 'vision/v3.0/analyze';
const imageUrl = "https://upload.wikimedia.org/wikipedia/commons/3/3c/Shaki_waterfall.jpg"; // will be sent as req body
var results;
// making API call to microsoft cognitive services API
try {
results = await axios({
method: 'post',
url: URI_BASE,
headers: {
'Content-Type': 'application/json',
'Ocp-Apim-Subscription-Key' : keys.ComputerVision
},
params: {
'visualFeatures': 'Tags',
'details': '',
'language': 'en'
},
data: {
"url": imageUrl,
}
});
} catch (err) {
return res.status(400).send(err);
}
// remove the common ones - indoor, outdoor, ground, wall, person, woman, man, ceiling, floor
const to_filter = results['data']['tags'];
_.remove(to_filter, (item) => {
return (item.name === 'indoor' || item.name === 'outdoor' || item.name === 'ground' || item.name === 'wall'
|| item.name === 'person' || item.name === 'woman' || item.name === 'man' || item.name === 'ceiling'
|| item.name === 'floor'
);
});
// searching for relevant songs and adding them to the playlist
var id;
try {
id = await search_and_add(req, res, spotifyAPI, to_filter, playlist_id);
} catch (err) {
if (err['statusCode'] === 401) {
req.logout();
return res.redirect('/');
}
else {
return res.status(400).send(err);
}
}
});
}
search_and_add = async (req, res, spotifyAPI, to_filter, playlist_id) => {
_.map(to_filter, async (tag) => {
try {
const song_details = await spotifyAPI.searchTracks(tag.name, { limit: 1 });
//const song_uri = song_details['body']['tracks']['items'][0]['id'];
console.log(song_details);
} catch (err) {
throw err;
}
});
return;
// figure out where to re direct user
};
我很肯定这是因为search_and_add函数中的map语句,但我不知道如何去掉它,提供相同的功能并使try catch块工作? 有人能帮忙吗?
对search_and_add
中的_.map(…)
调用的回调所创建的承诺没有执行任何操作。 它们只是被忽略,不被等待,当被拒绝时会引起警告。 想必您的意思是使用promise.all
?
function search_and_add(req, res, spotifyAPI, to_filter, playlist_id) {
return Promise.all(to_filter.map(async (tag) => {
// ^^^^^^^^^^^^
const song_details = await spotifyAPI.searchTracks(tag.name, { limit: 1 });
//const song_uri = song_details['body']['tracks']['items'][0]['id'];
console.log(song_details);
});
}
Promise.allSettled在node JS12版本及以上版本中可用。 如果您使用的节点少于12,则需要使用promise.all
AllSettled():promise.AllSettled()方法返回一个承诺,该承诺在所有给定的承诺实现或拒绝后进行解析,并带有一个对象数组,每个对象描述每个承诺的结果。
当您有多个异步任务,而这些任务彼此不依赖于才能成功完成时,或者您总是想知道每个承诺的结果时,通常会使用它。
All():Promise.all()方法接受一个iterable of promises作为输入,并返回一个Promise作为输出。 当所有输入的承诺都已解决并且非承诺已返回时,或者如果输入iterable不包含承诺时,返回的承诺将会解决。 当任何输入承诺拒绝或非承诺抛出错误时,它立即拒绝,并将以第一个拒绝消息/错误拒绝。
当有多个异步任务相互依赖才能成功完成时,它通常会使用,因为它不会等待,并且会在任何输入承诺拒绝时立即拒绝。
请参阅:
https://developer.mozilla.org/en-us/docs/web/javascript/reference/global_objects/promise/allsettled
https://developer.mozilla.org/en-us/docs/web/javascript/reference/global_objects/promise/all
https://sung.codes/blog/2019/05/18/promise-race-vs-promise-any-and-promise-all-vs-promise-allsettled/
const search_and_add = (req, res, spotifyAPI, to_filter, playlist_id) {
return Promise.allSettled(to_filter.map(async (tag) => {
const song_details = await spotifyAPI.searchTracks(tag.name, { limit: 1 });
//const song_uri = song_details['body']['tracks']['items'][0]['id'];
console.log(song_details);
return song_details;
}).catch(function(err){
console.log(err);
return err;
});
}
对于异步等待中的错误处理:
Async Await本质上是承诺的语法糖,如果Await语句出错,它将返回一个被拒绝的承诺,而不是在每个可以编写helper函数的地方添加try-catch,该函数包装我们的快速路由,以处理所有被拒绝的路由承诺。
const asyncMiddleware = fn =>
(req, res, next) => {
Promise.resolve(fn(req, res, next))
.catch(next);
};
然后像这样包装您的路由函数
router.get('/users/:id', asyncMiddleware(async (req, res, next) => {
/*
if there is an error thrown in getUserFromDb, asyncMiddleware
will pass it to next() and express will handle the error;
*/
const user = await getUserFromDb({ id: req.params.id })
res.json(user);
}));
注意:您也可以为此使用npm包异步中间件。