未处理的PromiseRejectionWarning:NodeJ中_.map中未处理的promise拒绝



当我运行下面的代码块时,总是会收到错误-未处理的PromiseRejection警告:未处理的promise拒绝。此错误源于在没有catch块的异步函数内部抛出,或拒绝未使用.catch((处理的promise。要在未处理的prompt拒绝时终止节点进程,请使用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执行任何操作。他们只是被忽视,没有被等待,当被拒绝时会引起警告。你大概是想在那里使用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函数进行包装

Promise.allSettled在node js 12及以上版本中可用。如果你使用的节点少于12,那么你需要使用Promise.all

Promise.allSettled((:Promise.allSettled((方法返回一个Promise,该Promise在所有给定的Promise都已实现或被拒绝后解析,其中包含一个对象数组,每个对象描述每个Promise的结果。

它通常用于多个异步任务,这些任务彼此不依赖才能成功完成,或者您总是想知道每个承诺的结果。

Promise.al((:方法Promise.all((将一个可迭代的Promise作为输入,并返回一个Promise作为输出。这个返回的promise将在所有输入的promise都已解析且非promise已返回时解析,或者如果输入可迭代不包含promise。一旦任何输入promise拒绝或非promise抛出错误,它就会立即拒绝,并将使用第一条拒绝消息/错误进行拒绝。

当有多个异步任务相互依赖才能成功完成时,通常会使用它,因为它不会等待,并且会在任何输入承诺被拒绝时立即拒绝。

请参阅:

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本质上是promise的语法糖,如果Await语句出错,它将返回一个被拒绝的promise。我们可以编写一个助手函数来包装我们的快速路由,以处理所有被拒绝的路由promise,而不是添加try-catch every。

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包异步中间件。

最新更新