看起来我不能使用异步函数作为Array.find()的第一个参数,我不明白为什么这段代码不能工作,这是幕后发生的事情?
function returnsPromise() {
return new Promise(resolve => resolve("done"));
}
async function findThing() {
const promiseReturn = await returnsPromise();
return promiseReturn;
}
async function run() {
const arr = [1, 2];
const found = await arr.find(async thing => {
const ret = await findThing();
console.log("runs once", thing);
return false;
});
console.log("doesn't wait");
}
run();
6条答案
按热度按时间dtcbnfnu1#
简单地说,
find
并不期望返回promise,因为它不适用于异步操作。它循环遍历数组,直到其中一个元素返回一个truthy值。一个对象,包括promise对象,是truthy,所以find在第一个元素上停止。如果你想要一个异步的find,你需要自己编写,你需要考虑的一个问题是你是想并行运行,还是想顺序运行,在进入下一个索引之前阻塞。
例如,这里有一个版本,它并行运行所有的承诺,然后一旦所有的承诺都得到解决,它会找到第一个产生真实值的承诺。
kdfy810k2#
以下是按顺序运行的TypeScript版本:
eblbsuwk3#
注意
Array.prototype.filter
是同步的,所以它不支持异步行为。我认为这同样适用于“find”属性。您可以随时定义自己的异步属性:)希望这对您有所帮助!vecaoik14#
其他答案提供了两种解决问题的方法:
1.并行运行承诺,并在返回索引之前等待所有承诺
1.按顺序运行的承诺,所以等待每一个单一的承诺,然后再移动到下一个。
假设你有五个承诺,它们在不同的时间完成:第一个在一秒后,第二个在两秒后,等等......第五个在五秒后。
如果我在找三秒后结束的那个:
1.第一个解决方案将等待5秒,直到所有承诺都得到解决。然后,它将查找匹配的解决方案。
1.第二个将在返回之前评估前三个匹配项(1 + 2 + 3 =6秒)。
下面是第三种选择,通常会更快:并行运行这些承诺,但只等到第一场比赛(“与它们赛跑”):3秒
当寻找一个不存在的项目时,解决方案1和3将花费相同的时间(直到所有承诺都被评估,这里是5秒),顺序方法(解决方案2)将花费1+2+3+4+5 = 15秒。
演示:https://jsfiddle.net/Bjoeni/w4ayh0bp
zbsbpyhn5#
我提出了一个解决方案,这里似乎没有涉及,所以我想分享一下。
async
函数(或返回承诺的函数)item
、index
和array
async
函数拒绝(抛出错误),不提前退出基于这些需求,我提出了下面使用
Promise.any
的解决方案,它将使用第一个满足的值解决问题,如果没有一个满足,则使用AggregateError
拒绝。现在我们可以用
async
函数并行搜索数组,并返回“最快”的解析结果。按顺序枚举数组
如果我们想枚举数组 in sequence,就像
Array.find
那样,那么我们可以做一些修改。现在,我们可以搜索数组 in sequence 并返回 first 解析结果。
sc4hvdpw6#
到目前为止,所有建议都缺少find的第二个参数,因此我提供两个进一步的建议:
第一个函数并行运行,并返回(就像原始函数一样)满足提供的测试函数的第一个值(相对于time),如果没有找到,则返回undefined。
第二个函数一个接一个地运行(考虑排序),并返回(就像原始函数一样)满足提供的测试函数的第一个值(相对于sorting),如果没有找到,则返回undefined。