这是我要讨论的代码。
view: async (req, res, next) => {
let formato = req.query.formato || 'details';
try {
let mode = Client.getMode(formato);
let options = {
columns: mode.columns,
withRelated: mode.withRelated,
};
let client_promises = [ ]
req.query['ids'].map( id => {
let client = Client.findById(id, options);
client_promises.push(client)
})
let response = await Promise.all(cliente_promesas)
return res.json({ success: true, data: response });
} catch (error) {
return next(error);
}
},
我了解到.map
函数在id数组上进行迭代,然后将其传递给Client.findById
,以便它可以返回要兑现的承诺,并在解决时获取客户端的数据。
现在,这些承诺被推送到一个数组中,然后被传递给Promise.all
,但是我真的不明白在哪里正在解决它们。当数组中的所有承诺都已解决时,Promise.all
是否只是传递了已解决的承诺?
我也了解await
只是让代码在继续之前等待了诺言的解决。
但是client_promises
中的承诺在哪里得到解决?
我知道这是基本知识,但对于我自己的一生,我似乎无法阅读足够的手册和指南来理解这一点。
答案 0 :(得分:2)
所有Promise.all
要做的是等待数组中传递给它的每个Promise完成。它不会“解雇”他们。实际上,传递的数组中的每个Promise甚至可能都处于已解决状态。从创建之初起,Promise就很“热”。
以您的示例为例,通过id获取项的功能会立即启动,并且同步返回一个Promise,该承诺最终将解析为通过id检索的任何对象。这很关键:Promise的返回不是不是异步部分,而是解决方案。
Promise.all
将所有诺言变成一个大诺言。
请考虑以下示例。我使用3个id并完全按照您的方式做,我称findById
并将函数(一个Promise)返回的内容放入数组promises
中。在findById
中,我还添加了一个 extra .then
调用,以演示这些承诺是“热”的,而不是等待Promise.all
调用的。另外请注意,我仍然返回p
。
到我们实际到达Promise.all
时,promises
中的所有Promise都已经解决,这就是为什么您看到它们首先打印到控制台的原因。它们都需要100-600毫秒才能解决,但是我们会主动等待整整1000毫秒,然后再调用Promise.all
。
不幸的是,没有(某种)API使用本机实现来显示Promise的状态。我认为曾经有一些使用诸如Bluebird和jQuery之类的用户土地库的方法,但是没有关于浏览器如何实现的方法。否则,我们可以在致电Promise.all
之前检查Promise,以查看它们是否已解决或待处理。
/**
* Utility function to wait a duration before resolving
* @param {number} [delay=100] How long to wait
* @returns {Promise<undfined>} Promise that will resolve after delay
*/
function timeout(delay = 100) {
return new Promise(resolve => {
setTimeout(resolve, delay);
});
}
/**
* Simulated find function that returns an object
* @param {number} id The id of the object to get
* @returns {Promise<object>} The fake DB object
*/
async function findById(id) {
await timeout((Math.random() * 500) + 100);
return {
id,
data: `foo-${id}`
};
}
(async function() {
const idsToGet = [1, 2, 3];
const promises = idsToGet.map(id => {
// Call to get the object
const p = findById(id);
// Let's add another listener here to know when they are done
p.then(r => {
console.log(`${r.id} is done`);
});
// Still return the actual Promise created by findById
return p;
});
// Just for kicks
await timeout(1000);
// Wait for EVERYTHING to be done
const res = await Promise.all(promises);
console.log(JSON.stringify(res, null, 4));
}());
答案 1 :(得分:0)
Promise.all()获取未解决的Promise的列表/数组。 就像是一个很大的 promise (承诺),它接受了所有未解决的承诺,直到所有承诺都得到解决,Promise.all()才被解决。
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise(function(resolve, reject) {
setTimeout(resolve, 100, 'foo');
});
Promise.all([promise1, promise2, promise3]).then(function(values) {
console.log(values);
});
在上面的示例中,您可以看到我们向Promise.all()传递了3个Promise 而当所有条件都满足时,只会触发。然后。
在您的情况下:
Client.findById(id, options);
必须返回要推送到client_promises数组中的Promise对象。 然后将它们提供给Promise.all(),直到这一点,您的承诺只是他们没有解决的承诺。
promise.all还会返回一个承诺,就像您在它前面一样等待。 它会等到他们解决后再给您一系列已解决的承诺。
答案 2 :(得分:0)
当您执行let client = Client.findById(id, options);
时,承诺实际上是“被解雇的” (即代码开始运行)。 await Promise.all
然后等待所有问题都解决,或者其中一个被拒绝,在这种情况下Promise.all也会以第一个promise拒绝的值被拒绝。