Использование асинхронной функции в Array.find () - PullRequest
0 голосов
/ 09 апреля 2019

Кажется, я не могу использовать асинхронную функцию в качестве первого аргумента 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

Ответы [ 3 ]

4 голосов
/ 09 апреля 2019

Проще говоря, find не ожидает возврата обещания, потому что оно не предназначено для асинхронных вещей. Он перебирает массив, пока один из элементов не приведет к возвращению истинного значения. Объект, включая объект обещания, является правдивым, и поэтому поиск останавливается на первом элементе.

Если вам нужен асинхронный эквивалент 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;
})
0 голосов
/ 10 апреля 2019

Я предполагаю, что вы пытаетесь что-то вроде следующего, которое использует await в цикле for, который прервется, когда будет найдено то, что вы ищете

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;}
0 голосов
/ 09 апреля 2019

Это может помочь вам заметить, что Array.prototype.filter является синхронным, поэтому не поддерживает асинхронное поведение.Я думаю, что то же самое относится и к «найти» свойство.Вы всегда можете определить собственное асинхронное свойство :) Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...