在Array.find()中使用异步函数

时间:2019-04-09 20:44:11

标签: javascript

似乎我无法使用异步函数作为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();

https://codesandbox.io/s/zk8ny3ol03

4 个答案:

答案 0 :(得分:4)

简而言之,find不会返回承诺,因为它不是用于异步事物的。它循环遍历数组,直到其中一个元素导致返回真实值。一个对象(包括一个promise对象)是真实的,因此查找在第一个元素上停止。

如果您想要异步等效的find,则需要自己编写。您需要考虑的一个问题是,是要并行运行事物,还是要顺序运行事物,在进入下一个索引之前会阻塞。

例如,这是一个并行运行它们的版本,然后,所有的诺言都得到解决后,它会找到第一个产生真实值的人。

async function findAsync(arr, asyncCallback) {
  const promises = arr.map(asyncCallback);
  const results = await Promise.all(promises);
  const index = results.findIndex(result => result);
  return arr[index];
}

//... to be used like:

findAsync(arr, async (thing) => {
  const ret = await findThing();
  return false;
})

答案 1 :(得分:2)

这是一个按顺序运行的TypeScript版本:

async function findAsyncSequential<T>(
  array: T[],
  predicate: (t: T) => Promise<boolean>,
): Promise<T | undefined> {
  for (const t of array) {
    if (await predicate(t)) {
      return t;
    }
  }
  return undefined;
}

答案 2 :(得分:0)

它可能会帮助您注意Array.prototype.filter是同步的,因此它不支持异步行为。我认为“ find”属性也是如此。您始终可以定义自己的异步属性:)希望能有所帮助!

答案 3 :(得分:0)

我的猜测是,您正在尝试执行以下操作,该操作在for循环中使用await,一旦找到所需内容,该操作就会中断

async function findThing(n) {
  return Promise.resolve({id: n})
}

async function run(wanted) {
  const arr = [1, 2, 3, 4, 5, 6];
  let found
  for (let n of arr) {
    const item = await findThing(n)
    if (item.id === wanted) {
      found = item;
      break
    } else {
      console.log('Not wanted:', JSON.stringify(item))
    }
  }

  console.log("found:", found);
}

const wanted = 4;
run(wanted);
.as-console-wrapper {max-height:100%!important;}