Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using an async function in Array.find()

Tags:

javascript

It seems I'm unable to use an async function as the first argument to Array.find(). I can't see why this code would not work what is happening under the hood?


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

like image 427
Laurie Poulter Avatar asked Apr 09 '19 20:04

Laurie Poulter


People also ask

Is Find function async?

Answer. Simply put, find does not expect a promise to be returned, because it is not intended for asynchronous things. It loops through the array until one of the elements results in a truthy value being returned.

How do I return an array from async function?

We have to call the async function from another function which can be asynchronous or synchronous (We can pass the array or choose to declare the array in the async function itself) and then return the array from the async function. The basic approach is to include a try-catch block.

Are array filters asynchronous?

Array. filter is not an asynchronous method, but what you appear to be confusing is the order of execution of a JavaScript programme. When the browser parses your code, the browser will look for named functions and add them to the list of declared names in the current scope (known as function hoisting).

Can async function return a value?

Async functions always return a promise. If the return value of an async function is not explicitly a promise, it will be implicitly wrapped in a promise. Note: Even though the return value of an async function behaves as if it's wrapped in a Promise.resolve , they are not equivalent.


1 Answers

Simply put, find does not expect a promise to be returned, because it is not intended for asynchronous things. It loops through the array until one of the elements results in a truthy value being returned. An object, including a promise object, is truthy, and so the find stops on the first element.

If you want an asynchronous equivalent of find, you'll need to write it yourself. One consideration you'll want to have is whether you want to run things in parallel, or if you want to run them sequentially, blocking before you move on to the next index.

For example, here's a version that runs them all in parallel, and then once the promises are all resolved, it finds the first that yielded a truthy value.

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;
})
like image 118
Nicholas Tower Avatar answered Sep 18 '22 19:09

Nicholas Tower