Использование ключевого слова `Async` при возврате объекта обещания - PullRequest
0 голосов
/ 18 января 2020

Я занимаюсь разработкой некоторых скриптов Nodejs и у меня возник вопрос по поводу использования ключевого слова asyn c в самом JS.

Например, рассмотрим, что у меня есть функция, которая возвращает обещание как это:

function myFunction () {
  ... some job
  return new Promise(async (resolve, reject) => {
    const innerResult = await someHeavyJob();
    ... some job
    resolve(innerResultThatIsManipulated);
  });
}

И я могу написать это по-другому:

async function myFunction () {
  ... some job
  const innerResult = await someHeavyJob();
  ... some job
  return innerResultThatIsManipulated;
}

Но у меня есть вопрос, что, если я выбираю первое решение, тогда я могу использовать ключевое слово async и это рекомендуется или нет? Например, что-то вроде этого:

async function myFunction () {
  ... some job
  return new Promise(async (resolve, reject) => {
    const innerResult = await someHeavyJob();
    ... some job
    resolve(innerResultThatIsManipulated);
  });
}

Чтобы подчеркнуть, что это асинхронный c метод, который возвращает обещание (не простой объект) во всех путях его кода.

Итак, каков рекомендуемый способ использования?

Ответы [ 3 ]

2 голосов
/ 18 января 2020

Это анти-шаблон:

return new Promise(async (resolve, reject) => {
  const innerResult = await someHeavyJob();
  // ... some job
  resolve(innerResultThatIsManipulated);
});

Вы не должны создавать новое обещание с new Promise, когда обратный вызов конструктора собирается создать обещание, а затем вызвать resolve с этим (манипулировать ) обещанный результат.

Это действительно должно быть закодировано следующим образом:

return someHeavyJob().then((innerResult) =>
  // ... some job
  return innerResultThatIsManipulated;
});

Разница

Так что после вышеприведенного замечания ваш вопрос действительно о добавлении ключевого слова async к этому определение функции:

function myFunction () {
  // ... some job 1
  return someHeavyJob().then((innerResult) =>
    // ... some job 2
    return innerResultThatIsManipulated;
  });
}

Вот основные различия:

  • Если возбуждается исключение до вызова .then() - так в «некотором задании 1» или при вызове someHeavyJob - тогда версия async по-прежнему будет возвращать обещание (которое имеет отклоненное состояние), в то время как не-1026 * версия вызовет эту ошибку.

  • Также обещание, возвращаемое версией async, равно , а не , которое возвращено в операторе return. Тот, который async возвращает, является отдельным обещанием, решение которого (планируется быть) связано с тем, которое вы предоставляете для оператора return.

Вы можете принять это разница, написав не-async версию, как это:

function myFunction () {
  return Promise.resolve().then(() => {
    // ... some job 1
    return someHeavyJob().then((innerResult) =>
      // ... some job 2
      return innerResultThatIsManipulated;
    });
  });
}

Или, лучше, сплющенный в одну цепочку:

function myFunction () {
  return Promise.resolve().then(() => {
    // ... some job 1
    return someHeavyJob();
  }).then((innerResult) =>
    // ... some job 2
    return innerResultThatIsManipulated;
  });
}

Это лучше имитирует то, что * Версия 1048 * делает: один обеспечивает для возврата обещания.

Итак, простое добавление async не дает функции, которая гарантированно будет вести себя одинаково , Если ваша цель состоит в том, чтобы всегда возвращать обещание, даже если во время выполнения функции возникает ошибка, тогда определенно go для async. Но как только вы это сделаете, часто есть веские причины также использовать синтаксис await: это просто делает код более читабельным.

1 голос
/ 18 января 2020

Из всех приведенных вами примеров только второй является правильным. Причина этого в том, что Promise - это функция конструктора (следовательно, вы используете ее с new), которая принимает обычную функцию, а не другую Promise в качестве аргумента.

Пример 1

Интерпретатор переводит ваш первый пример во что-то вроде этого (теоретически):

new Promise( new Promise((resolve, reject) => { ... }))

Это не то, что вы хотите, и также считается анти-паттерном. Вместо этого вам нужно:

new Promise((resolve, reject) => { ... })

Более того, кажется, что у вас уже есть функция (someHeavyJob), которая приводит к Promise. Почему вы хотите обернуть это в другой Promise? Просто используйте .then метод Promise, возвращаемый someHeavyJob, чтобы преобразовать все, что он вам дает.

В конце концов, у вас останется что-то вроде:

function myFunction() {
  // ... some job
  return someHeavyJob().
    then( result => {
      // ... some job with result
    })
}

Пример 3

Третий пример неверен по тем же причинам. Пример 1 неверен, как с технической, так и с логической точки зрения.

Общие эмпирические правила

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

Попробуйте придерживаться любого из двух соглашений (используя Promise или используя async / await ). Смешивайте их только в том случае, если вам это действительно нужно.

Лично я стараюсь придерживаться Promise вместо async / await, потому что они часто портят людей и - для меня - они оба не Это не приносит большой пользы, кроме того, что код выглядит «лучше». Впрочем, это только мое личное мнение.

1 голос
/ 18 января 2020

MDN говорит:

Объявление функции asyn c определяет асинхронную функцию - функцию, которая возвращает объект AsyncFunction. Асинхронные функции работают в отдельном порядке, чем остальная часть кода, посредством события l oop, , возвращающего неявное обещание в качестве его результата. Но синтаксис и структура кода с использованием асин c функций выглядят как стандартные синхронные функции .

Делая это:

async function myFunction () {
  return new Promise(async (resolve, reject) => {
    const innerResult = await someHeavyJob();
    resolve(innerResult);
  });
}

Вы возвращая неявное обещание, которое возвращает обещание. Вы спросили, будет ли это интересный подход, чтобы сделать код более читабельным, я полагаю, что это сбивает с толку больше, чем разъясняет. функция asyn c, которая на самом деле содержит только это обещание, содержащее только эту функцию asyn c, первая, о которой я говорил, не последняя, ​​я имею в виду вторую, вы следовали? Редактировать: вы на самом деле редактировали это фрагмент, это было только для примера)

MDN добавляет:

Цель асинхронного ожидания / ожидания - упростить синхронное использование обещаний

В моем понимании функция asyn c является альтернативой обещанию, а не расширению, скажем так. Поэтому, кажется, не стоит объединять их так, как вы предлагали.

...