Можно ли вернуть значение из обратного вызова внутри асинхронной функции без использования Promise?

Очень простой вопрос, я знаю, когда пишу такую ​​асинхронную функцию:

const res = (async () => 'hello')();
console.log(await res);

Он должен записать: "привет".

Но, допустим, я хочу тайм-аут результата внутри моей асинхронной функции, мне пришлось бы создать новое обещание, чтобы я мог обернуть в него тайм-аут обратного вызова, например:

const res = (async () => 
   new Promise(resolve => 
     setTimeout(
       () => resolve('hello'), 1000
     )
   )
)();
console.log(await res);

Что ж, если async уже возвращает обещание, зачем мне создавать новое обещание внутри функции, которая уже является обещанием, чтобы сделать что-то столь же простое, как это? Я что-то упустил или это действительно так? Разве не было бы лучше, если бы я мог просто сделать что-то подобное по-своему? Это вообще возможно? Например:

const res = (async () => 
  setTimeout(
    () => resolve('hello'), 1000
  )
)();
console.log(await res);

person Elias Dal Ben    schedule 11.02.2019    source источник
comment
Вы не можете, потому что в цепочке обещаний нет resolve() функции.   -  person unional    schedule 12.02.2019


Ответы (3)


В конечном итоге вам нужно преобразовать функцию «стиля обратного вызова» в обещание, чтобы вы не могли обойтись без этого обещания. Если вы думаете, что это немного некрасиво, я бы предложил использовать или создать служебную функцию, которая сделает это за вас.

Кроме того: если вы не используете await в функции, на самом деле нет веских причин отмечать ее как асинхронную. Это лучше:

const res = new Promise(resolve => 
  setTimeout(
    () => resolve('hello'),
    1000
  )
);

console.log(await res);

Я думаю, что хороший способ думать об async / await состоит в том, что он упрощает написание определенных шаблонов обещаний, но не все, что вы можете сделать с простым обещанием, также можно сделать с помощью async / await. async / await делает общий шаблон (НАМНОГО) более разборчивым.

person Evert    schedule 11.02.2019

Вообще говоря, new Promise предназначен для устаревших обратных вызовов. И в идеале вы хотите максимально предотвратить их использование.

Итак, в вашем примере вы используете setTimeout, а затем разрешаете строку hello. Вместо этого было бы разумнее создать функцию задержки, которую вы могли бы использовать снова, а затем просто вернуть "hello"

eg.

const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));

async function test() {

  const res = (async () =>  {
    await delay(1000);
    return "hello";
  })();
  
  console.log(await res);
  
}

test();

person Keith    schedule 11.02.2019

Что ж, если async уже возвращает обещание, зачем мне создавать новое обещание внутри функции, которая уже является обещанием, чтобы сделать что-то столь же простое, как это?

Функция async имеет три особенности:

  • Это создает обещание
  • Обещание разрешается с возвращаемым значением
  • Вы можете использовать await внутри него

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

Это не делает его универсальным инструментом для замены всех других применений Promise.

Для этого вам все еще нужен один.


Например:

const res = (async () => 
  setTimeout(
    () => resolve('hello'), 1000
  )
)();
console.log(await res);

Если бы это сработало, тогда функция resolve возникла бы из ниоткуда, а значение return не было бы значением, которое функция разрешила.

Это потеряло бы одно из преимуществ async функций.


JavaScript - это большой набор инструментов. Для разных работ подходят разные инструменты.

person Quentin    schedule 11.02.2019