Home > Enterprise >  Why this promise is never resolved? (Simple JavaScript in Chrome)
Why this promise is never resolved? (Simple JavaScript in Chrome)

Time:09-06

async function test(){
  setTimeout(function(){return 1}, 100)
};
test().then(console.log); // Never displayed

If the setTimeout wrap is removed, it works:

async function test(){
  return 1;
};
test().then(console.log); // Displayed

CodePudding user response:

First, you forgot the return statement in the test function. Without a return statement, the function returns a Promise which resolves to undefined.

Second, setTimeout does not return a promise. Instead, you have to create it explicitly.

It should be something like this.

async function test() {
  return new Promise((resolve) => setTimeout(() => resolve(1), 100))
}

But your code is equivalent to the following because you do not use setTimeout in any way.

async function test() {
  return undefined
}

There are two options to create an async function. Historically the first one is that function accepts a callback. The second option is to return a promise from the function.

Many library functions accept a callback and call the callback when the async event happens. An example of such a function is the setTimeout.

To use a function which accepts a callback with await, you can wrap it in a new Promise.

For example, we have a library function libFunc(..., callback) where callback is a function which accepts some arguments.

You can create a new promise like this.

const result = await new Promise(
  (resolve) => libFunc(/*some arguments*/,
    (callbackArg) => resolve(callbackArg)))

You can check my post on the topic Async function from callback in JavaScript

CodePudding user response:

The below function does not return anything. Neither is it a promise, that it would resolve with a value. It is just a function that sets a timer for a function that (will run in window's context) and return 1. The returned value is not captured anywhere.

async function test(){
  setTimeout(function(){return 1}, 100)
};

To access the value from setTimeout you will have to wrap it in a promise and let the promise resolve with that value.

async function test(){
  return new Promise((resolve,reject) => setTimeout(function(){resolve(1);}, 100));
};
test().then(console.log);


async function test2(){
  return 1;
};
test2().then(console.log); // Displayed

Another way to access value inside setTimeout, without using promises is to pass callbacks like below.

async function test(callback){
  setTimeout(function(){callback(1)}, 100)
};
test(console.log);

The above code shows why it is easier to reason about code with promises. Any piece of code, which you want to have access to the value (from inside setTimeout) will have to be in the callback. This gets messy

  • Related