Использование промисов ES6 и Async/await

внешний интерфейс JavaScript API Promise
Использование промисов ES6 и Async/await

Как вы, наверное, знаете, среда выполнения языка Javascript представляет собой «один поток».

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

Преимущество этого режима в том, что его относительно просто реализовать, а среда выполнения относительно проста; недостаток в том, что пока одна задача занимает много времени, последующие задачи должны быть поставлены в очередь, что задержит выполнение задачи. всю программу. Обычные браузеры не отвечают (притворная смерть), часто потому, что определенный фрагмент кода Javascript выполняется в течение длительного времени (например, бесконечный цикл), в результате чего вся страница зависает на этом месте, и другие задачи не могут быть выполнены.

Для решения этой проблемы язык Javascript разделяет режимы выполнения задач на два типа: синхронный и асинхронный.

1. Обратный звонок

Обратные вызовы — это самый простой метод асинхронного программирования.

Предположим, что есть две функции f1 и f2, причем последняя ожидает результата выполнения первой.

f1();
f2();

Если f1 требует много времени, рассмотрите возможность перезаписи f1 и записи f2 в качестве функции обратного вызова для f1.

function f1(callback){
  setTimeout(function () {
    // f1的任务代码
    callback();
  }, 1000);
}

Код выполнения становится следующим

f1(f2);

Таким образом, мы превращаем синхронную операцию в асинхронную, и f1 не будет блокировать работу программы, что эквивалентно выполнению основной логики программы в первую очередь и задержке выполнения трудоемких операций. Преимущество функции обратного вызова состоит в том, что она проста, легка для понимания и развертывания. Недостаток в том, что она не способствует чтению и сопровождению кода. Различные части сильно связаны, процесс будет очень хаотичным и для каждой задачи может быть указана только одна функция обратного вызова.

2.Promise

PromisesобъектCommonJSСпецификация, предложенная рабочей группой для обеспечения единого интерфейса для асинхронного программирования.

Проще говоря, его идея заключается в том,Каждая асинхронная задача возвращает объект Promise с методом then, который позволяет указать функцию обратного вызова.Появление промисов значительно улучшило дилемму асинхронности, избегая ада обратных вызовов и улучшая уровни вложенности.

Основные API

  1. Promise.resolve()
  2. Promise.reject()
  3. Promise.prototype.then()
  4. Promise.prototype.catch()
  5. Promise.all() // все выполнено
  6. Promise.race() // Гонка, просто завершите одну

Для ознакомления с конкретным API см. Ruan Yifeng Great GodНачало работы с ECMAScript 6Здесь я привожу реализацию нескольких простых сценариев

Имитация двух асинхронных запросов

Чтобы сделать код кратким, обещанияrejectedСвязанные с состоянием методы reject() и catch() опущены.

  // 1请求
  function getData1 () {
    return new Promise(function (resolve, reject) {
      setTimeout(() => {
        console.log('1执行了')
        resolve('请求到模拟数据1111拉')
      }, 2000)
    })
  }
  // 2请求
  function getData2 (params) {
    return new Promise(function (resolve, reject) {
      setTimeout(() => {
        console.log('2执行了')
        resolve('请求到模拟数据22222拉!params:' + params)
      }, 1500)
    })
  }

обещание реализует асинхронную очередь асинхронного обратного вызова

После того, как запрос 1 завершен, параметр ответа 1 передается в 2, и запрос 2 отправляется

  function promiseDemo () {
    getData1()
      .then(res => {
        return getData2(res)
      })
      .then(res => {
        console.log(res)
      })
  }
  promiseDemo()
  // 1执行了
  // 2执行了
  // 请求到模拟数据22222拉!params:请求到模拟数据1111拉   用时 3500 ms

promise.all() реализует асинхронные обратные вызовы одновременно со всеми завершениями

1 запрос и 2 запроса отправляются одновременно, и оба ответа принимаются и выполняются

  function promiseDemo () {
    Promise.all([getData1(), getData2()]).then(function (res) {
      console.log(res)
    })
  }
  // 2执行了
  // 1执行了
  // ["请求到模拟数据1111拉", "请求到模拟数据22222拉!params:undefined"]   用时 2000 ms

promise.race() реализует параллельную гонку асинхронных обратных вызовов.

1 запрос и 2 запроса отправляются одновременно, и один из них будет выполнен после получения запроса

  function promiseDemo () {
    Promise.race([getData1(), getData2()]).then(function (res) {
      console.log(res)
    })
  }
  // 2执行了
  // 请求到模拟数据22222拉!params:undefined    用时 1500 ms
  // 1执行了   

Поэтому объект Promise по-прежнему очень полезен, а управление асинхронным процессом значительно улучшено..then()метод может быть цепным. Но.then() .catch()Использование также делает код очень уродливым и глубоко вложенным, поэтомуasync/awaitвышел

Async/await

Async/await — это новый способ написания асинхронных программ на Javascript. Асинхронные методы прошлого — это не что иное, как функции обратного вызова и промисы. Но Async/await построен на промисах.

Как использовать асинхронные функции

Давайте посмотрим на Жуань Ифэна, великого бога.Начало работы с ECMAScript 6пример

async function timeout(ms) {
  await new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
}

async function asyncPrint(value, ms) {
  await timeout(ms);
  console.log(value);
}

asyncPrint('hello world', 50);

Приведенный выше код указывает, что hello world выводится через 50 миллисекунд. Кроме того, асинхронную функцию можно рассматривать как несколько асинхронных операций, упакованных в объект Promise, а команда await — это синтаксический сахар внутренней команды then.

Рассмотрим конкретные примеры

async реализует асинхронную очередь асинхронного обратного вызова

После того, как запрос 1 завершен, параметр ответа 1 передается в 2, и запрос 2 отправляется

Вышеприведенный метод реализации обещания заключается в последовательном вызове then, но использование async будет более кратким и понятным.

  async function asyncDemo () {
    const r1 = await getData1()
    const r2 = await getData2(r1)
    console.log(r2)
  }
  // 1执行了
  // 2执行了
  // 请求到模拟数据22222拉!params:请求到模拟数据1111拉   用时 3500 ms

Асинхронный код реализован в синхронной записи. Дождавшись завершения выполнения асинхронной функции getData1, отправьте возвращаемое значение и назначьте его r1, передайте r2 и выполните r2.

асинхронный асинхронный обратный вызов

1 запрос и 2 запроса отправляются одновременно с указанием порядка поступления запросов

Предположим, у нас есть такое бизнес-требование, два одновременных запроса, но что мы должны сделать, чтобы указать порядок, в котором будут поступать запросы? Вот код великого бога Жуань Ифэна

  async function asyncDemo2 () {
    const arr = [getData1, getData2]
    const textPromises = arr.map(async function (doc) {
      const response = await doc()
      return response
    })
    // 按次序输出
    for (const textPromise of textPromises) {
      console.log(await textPromise);
    }
  }
  // 2执行了            (因为2是 1500ms后执行) 所以2先执行
  // 1执行了
  // 请求到模拟数据1拉  (for .. of )规定了输出的顺序
  // 请求到模拟数据22222拉!params:undefined

В приведенном выше коде, несмотря на то, что параметр метода карты является асинхронной функцией, он выполняется одновременно, поскольку последовательно выполняется только внутренняя часть асинхронной функции, а внешняя не затрагивается. Более поздний цикл for..of использует await внутри, поэтому он обеспечивает последовательный вывод.

Как можно реализовать такие потребности БТ.

асинхронная сводка

Также недостатком является то, что он делает асинхронный код более не очевидным, но лучше всего выбрать наиболее подходящее асинхронное программирование в соответствии с реальной ситуацией. async — это синтаксический сахар для функций генератора. Так что, если вы хотите глубже понять внутренние принципы, идите и посмотритеGeneratorфункция поставить