简体   繁体   中英

async/await logs to the console but returns no value and returns `Promise { pending }`

I have been trying to get the result of this asynchronous function to no degree of success for the past few hours. I have checked the past similar questions and solutions but nothing has worked for this specific case.

This particular code below logs the value when I run console.log:

const okay = async () => {
  console.log(await getTimezoneLabel(timezone));
};

okay();

The code below logs Promise {pending} instead of a value to the console which is baffling

const okay = async () => {
  return await getTimezoneLabel(timezone);
};

let result = okay();

console.log(result);

Here is the getTimezoneLabel function itself:

async function getTimezoneLabel(timezone) {
  const timezoneObject = await convertTimezone('original', timezone);
  return timezoneObject[0].label;
}

Here is the convertTimezone function which the getTimezoneLabel function references:

import timezonesList from '../timezone-list';

async function convertTimezone(labelStyle, timezone) {
  const spacetime = (await import('spacetime')).default;
  const soft = (await import('timezone-soft')).default;

  const timezones = Object.fromEntries(Object.entries(timezonesList).filter(([key]) => key.includes(timezone)));

  return Object.entries(timezones)
    .reduce((selectOptions, zone) => {
      const now = spacetime.now(zone[0]);
      const tz = now.timezone();
      const tzStrings = soft(zone[0]);

      let label = '';
      let abbr = now.isDST()
        ? // @ts-expect-error
          tzStrings[0].daylight?.abbr
        : // @ts-expect-error
          tzStrings[0].standard?.abbr;
      let altName = now.isDST() ? tzStrings[0].daylight?.name : tzStrings[0].standard?.name;

      const min = tz.current.offset * 60;
      const hr = `${(min / 60) ^ 0}:` + (min % 60 === 0 ? '00' : Math.abs(min % 60));
      const prefix = `(GMT${hr.includes('-') ? hr : `+${hr}`}) ${zone[1]}`;

      switch (labelStyle) {
        case 'original':
          label = prefix;
          break;
        case 'altName':
          label = `${prefix} ${altName?.length ? `(${altName})` : ''}`;
          break;
        case 'abbrev':
          label = `${prefix} ${abbr?.length < 5 ? `(${abbr})` : ''}`;
          break;
        default:
          label = `${prefix}`;
      }

      selectOptions.push({
        value: tz.name,
        label: label,
        offset: tz.current.offset,
        abbrev: abbr,
        altName: altName,
      });

      return selectOptions;
    }, [])
    .sort((a, b) => a.offset - b.offset);
}

How can I get this to work?

Thank you so much in advance.

I'm simplifying quite a lot here, but it helps to understand. When you declare a function as async , what it does is wrap the function in a Promise. So, for example, this function:

async function something(){ return "hello world" }

can be read like:

function something(){
  return new Promise((resolve, reject) => {
    resolve("hello world")
  })
}

In a nutshell, a Promise just schedules the execution of a function (in this case something ) for later. So, we can only read the returned value later, when it's ready. When you call something() , it returns a Promise which is pending because it hasn't been executed yet (its execution is put on hold in a queue). You can learn more about how this works by reading about the event loop, the call stack and event queue.

To get the returned value of a Promise, we use a method called .then((value) => {}) which returns in the variable value the returned value of the function (in our case, value will contain "hello world" ). So:

let r = something()
console.log(r) // Promise pending
r.then((value) => {
  console.log(value) // "hello world"
})

If you want to use the value , you are gonna have to either:

  • Put your code inside the .then() and continue there
  • Put your code inside an async function and use await in front of the call
async function run(){
  let value = await something()
  console.log(value) // "hello world"
  // do things with value
}

run()

An async function return a promise. Try that:

const okay = async () => {
  return await getTimezoneLabel(timezone);
};

okay().then(result=>console.log(result));

or if you call okay() inside another async function you may use await syntax:

// should be inside async function
const result = await okay();

This is a similar question that is already answered with some good explanation

Well basically async function returns a promise. You can use use let somevariable = await okay() inside an async function OR You could do it like

okay().then((resp)=>{
   console.log(resp)
})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM