我正在尝试创建一系列承诺并使用Promise.all
调用它们。
我在将函数正确推入数组时遇到问题,似乎是在调用它们而不是插入并等待Promise.all()
。
function findSpecialAbility(players, gameId, message) {
return new Promise(function(resolve, reject) {
let playersWithSpecials = _.reject(players, function(p) {
return p.role === 'alphaWolf' ||
p.role === 'betaWolf' ||
p.role === 'villager' ||
p.role === 'alchemist' ||
p.targetId === 0 ||
p.abilityUsed === true;
});
if (playersWithSpecials.length === 0) {
resolve();
} else {
let specialsToUse = [];
for (let i = 0, j = playersWithSpecials.length; i < j; i++) {
specialsToUse.push(useSpecialAbility(playersWithSpecials[i], gameId, message, players));
}
//Promise.all(specialsToUse).then(r = > console.log(r));
}
});
}
// Using promise below because some of the role will have database updates.
function useSpecialAbility(playerData, gameId, message, players) {
return new Promise(function(resolve, reject) {
if (playerData.role === 'seer') {
let getTargetData = _.find(players, {
id: playerData.targetId
});
message.guild.members.get(playerData.id).send(`Your target is a ${getTargetData.role}!`);
resolve('foo');
}
});
}
答案 0 :(得分:5)
它们似乎被调用而不是插入并等待
Promise.all()
您似乎希望在致电Promise.all
时,承诺内的代码同时运行。
如果这就是你想要的,那么在promises中包装代码可能不是你想要的。
相反,你需要在一个普通的ole函数中包装你想要稍后运行的代码。您可以将这些函数添加到数组中,然后在循环中调用每个函数。根据代码的外观,您可能甚至不需要承诺。
请参阅以下示例:
// this function returns another function `runnable` and can be called later (synchronously) to get the result
function runLater (index) {
return function runnable() {
console.log(`this code is ran later. from ${index}`);
return `from ${index}`;
}
}
console.log('this is run now');
const tasks = [];
for (let i = 0; i < 3; i += 1) {
tasks.push(runLater(i));
}
console.log('this is run');
// use Array.prototype.map to map the array of functions to what they return by invoking each one.
const valuesOfTasks = tasks.map(task => task());
console.log({valuesOfTasks});
console.log('this is run after');
&#13;
当您处理异步控制流时,您只需要承诺。延迟执行可以同步完成,只需将一段代码包装在一个函数中即可。当您想要执行该代码时,只需调用该函数。
编辑:
在继续使用我的代码之前,我需要等待所有useSpecialAbility完成。他们中的一些人会从数据库中写入/读取,这就是我使用承诺的原因。
在这种情况下,您将不得不使用Promise.all
,但如果您希望它们全部同时运行,您仍然需要将这些承诺包装在没有参数的函数中。
promises的代码块实际上是同步运行的(当你调用.then
或Promise.all
时运行块)所以如果你仍然希望稍后运行promises,你仍然可以将它们包装在函数中
见这个例子:
function waitThenSay(milliseconds, message) {
return new Promise(resolve => {
console.log(`waiting to say: "${message}"...`)
setTimeout(() => {
// log to console for immediate side-effect
console.log(message.toUpperCase() + '!');
// also resolve with the message
resolve(message);
}, milliseconds);
});
}
console.log('this is run first');
// tasks is an array of functions that return promises
const tasks = [];
for (let i = 1; i <= 3; i += 1) {
tasks.push(() => waitThenSay(i * 2000, `hello from task ${i}`));
}
console.log('this is run second');
// execute the tasks by mapping each function to their invocation
const arrayOfPromises = tasks.map(task => task())
// call Promise.all on that array
Promise.all(arrayOfPromises).then(result => {
console.log({result});
});
&#13;
希望这有帮助!
答案 1 :(得分:0)
我想添加一种相当简单的异步/等待方法,用于将promise推送到数组并在其后使用Promise.all。
async (req, res, next) => {
try{
const promises = [];
//Conditionally add promises to the promises array
if(req.user.hobby === "Hockey")
promises.push(() => Hobby.find({name: "Hockey"}));
else
promises.push(() => Hobby.find({}));
if(req.user.country === "Canada")
promises.push(() => User.find({country: "Canada"}));
//Execute the promises in Promise.all()
const docs = await Promise.all(promises.map(promise => promise()));
if(docs.length === 0){
var err = new Error('No documents found');
err.status = 404;
return next(err);
}
if(docs[1])
console.log(docs[1]); //array of User docs with country field value set to Canada
console.log(docs[0]); //array of all hobbys or only hobbys with the name field set to Hockey
res.json(docs);
}
catch(err){
return next(err);
}
}