Позвольте вам понять async/await за один раз и решить ад обратного вызова

внешний интерфейс JavaScript Promise
Позвольте вам понять async/await за один раз и решить ад обратного вызова

Что такое асинхронность?

Добро пожаловать, чтобы оставить сообщение для обсуждения

asyncфункцияGeneratorСинтаксический сахар для функций. использовать ключевые словаasyncдля представления, используется внутри функцииawaitдля обозначения асинхронности. По сравнению сGenerator,asyncУлучшение функции заключается в следующих четырех пунктах:

  • Встроенный привод.GeneratorВыполнение функции должно зависеть от исполнителя, иasyncУ функции есть свой исполнитель, а метод вызова такой же, как и у обычных функций.

  • лучшая семантика.asyncиawaitПо сравнению с*иyieldболее семантический

  • более широкая применимость.coсоглашения модулей,yieldЗа командами могут следовать только функции Thunk или объекты Promise. иasyncфункциональныйawaitЗа командой может следовать обещание или значение примитивного типа (число, строка, логическое значение, но это эквивалентно синхронной операции)

  • Возвращаемое значение является обещанием.asyncВозвращаемое значение функции — это объект Promise, который более удобен, чем объект Iterator, возвращаемый функцией Generator, и может использоваться напрямую.then()способ вызова

Вот сводка ссылок из:Понимание асинхронности/ожидания

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

как пользоваться

После объявления его можно вызвать

async function asyncFn() {
  return 'hello world';
}
asyncFn();

Это означает, что это асинхронная функция и возвращаемый результат

     

async означает, что в функции есть асинхронные операции
await означает, что следующее выражение должно ожидать результата.

возвращаетpromiseобъект, состояниеresolved, параметрreturnзначение . Затем посмотрите на следующую функцию

async function asyncFn() {
    return '我后执行'
}
asyncFn().then(result => {
    console.log(result);
})
console.log('我先执行');

Результат вышеприведенного выполнения должен распечатать сначала'我先执行', хотя вышеasyncFn()Сначала выполнить, но асинхронная функция определена и не повлияет на выполнение последующих функций.

теперь понятноasyncОсновное использование, какие еще функции есть?

asyncОпределенная функция внутренне возвращает значение по умолчаниюpromiseобъект, если функция выдает исключение или возвращаетreject, сделает функциюpromiseстатус не выполненreject.

async function e() {    
    throw new Error('has Error');
}
e().then(success => console.log('成功', success))   
   .catch(error => console.log('失败', error));

Мы видим, что внутри функция бросает异常,возвращениеreject,asyncПосле того, как функция получена, определяется, что выполнение не может войтиcatch, выводится возвращенная ошибка.

async function throwStatus() {    
    return '可以返回所有类型的值'
}
throwStatus().then(success => console.log('成功', success))             
             .catch(error => console.log('失败', error));

//打印结果

成功 可以返回所有类型的值

asyncФункция получает возвращаемое значение и обнаруживает, что оно не异常илиreject, то решение успешное, здесь можноreturnзначения различных типов данных,false,NaN,undefined... короче обаresolve

Но возврат следующих результатов сделаетasyncОценка функции не удаласьreject

  1. Содержит внутри непосредственно используемые и необъявленные переменные или функции.

  2. внутренне выдает ошибкуthrow new Errorили вернутьсяrejectгосударствоreturn Promise.reject('执行失败')

  3. Ошибка в выполнении метода функции (🌰: Объект использует push()) и т.д...

Еще одно, вasync, результат должен бытьreturnвернись, иначе неважно, будет ли оно выполненоrejectвсе ещеresolvedЗначенияundefine, рекомендуются стрелочные функции.

Остальные возвращенные результаты являются суждениямиresolvedВыполнено успешно.

//正确reject方法。必须将reject状态return出去。
async function PromiseError() {    
   return Promise.reject('has Promise Error');
}

//这是错误的做法,并且判定resolve,返回值为undefined,并且Uncaught报错
async function PromiseError() {
  Promise.reject('这是错误的做法');
}

PromiseError().then(success => console.log('成功', success))              
              .catch(error => console.log('失败', error));

Мы видим, что во второй строке большеPromiseОбъектная печать, пофиг, это вChromeПоведение консоли по умолчанию, и мы обычно присваиваем консоли значения, имеют тот же эффект. если последний执行语句или表达式нетreturnвозвращаемое значение, по умолчаниюundefined, проведите небольшой эксперимент.

var a = 1;
//undefined
------------------------------------------------------------
console.log(a);
//1
//undefined
------------------------------------------------------------
function a(){ console.log(1) }
a();
//1
//undefined
------------------------------------------------------------
function b(){ return console.log(1) }
b();
//1
//undefined
------------------------------------------------------------
function c(){ return 1}
c();
//1
------------------------------------------------------------
async function d(){
    '这个值接收不到'
}
d().then(success => console.log('成功',success));
//成功  undefined
//Promise { <resolved>: undefined }
-----------------------------------------------------------
async function e(){
    return '接收到了'
}
e().then(success => console.log('成功',success));
//成功  接收到了
//Promise { <resolved>: undefined }

последняя строкаPromise { <resolved> : undefined }потому что вернулсяconsole.logОператор выполняется без возвращаемого значения.

d().then(success => console.log('成功',success)}
等同于
d().then(function(success){ 
            return console.log('成功',success);
        });

js сам по себе однопоточный, через v8 у нас могут быть «асинхронные» возможности

Познакомившись с асинхронностью, давайте поговорим об ожидании.

что ждет?

awaitОзначает асинхронное ожидание (асинхронное ожидание). Это ключевое слово можно использовать только тогда, когдаasyncиспользуется в определенной функции. любойasyncфункция возвращает по умолчаниюpromiseИ этоpromiseРазрешение значения all будет возвращаемым значением функции, аasyncФункция должна ждать, пока все внутренниеawaitкомандаPromiseПосле выполнения объекта происходит изменение состояния.

Например, await — это ученик, async — это школьный автобус, и вы должны дождаться, пока все сядут за руль, прежде чем ехать.

Другими словами, я должен дождаться выполнения всех функций `await`, прежде чем сообщить `promise`, удалось ли мне это или не удалось, и выполнить `then` или `catch`
async function awaitReturn() {     
    return await 1
};
awaitReturn().then(success => console.log('成功', success))
             .catch(error => console.log('失败',error))

В этой функции естьawaitфункция, async будет ждать, покаawait 1Он вернется после завершения этого шага.promiseсостояние, без сомнения, суждениеresolved.

Многие люди думаютawaitОн будет ждать, пока не будет выполнено следующее выражение, прежде чем продолжить выполнение следующего кода.Фактическиawaitявляется признаком уступки потока.awaitСледующая функция будет выполнена первой (например, Fn в await Fn(), а не следующая строка кода), а затем она выскочит из всего списка.asyncфункция для выполнения кода позади стека js. После того, как текущий раунд цикла событий будет выполнен, он вернется кasyncФункция ожидает возвращаемого значения выражения, следующего за await****, если возвращаемое значение не равноpromiseпродолжать выполнятьasyncКод функции, иначе он вернетpromiseположить вPromiseОчередь (Очередь заданий Promise)

Давайте рассмотрим простой пример

const timeoutFn = function(timeout){ 
	return new Promise(function(resolve){
		return setTimeout(resolve, timeout);
               });
}

async function fn(){
    await timeoutFn(1000);
    await timeoutFn(2000);
    return '完成';
}

fn().then(success => console.log(success));

Здесь можно было бы использовать стрелочную функцию для удобства, но для того, чтобы прочитать суть, она была заменена на запись ES5.Все функции ожидания в приведенной выше функции выполнения будут возвращать статус, а результат будет всплывать через 3 секунды исполнение.'完成'.

Обычно за командой await следует обещание, в противном случае оно будет преобразовано в обещание, которое немедленно разрешается.

Вы также можете написать

function timeout(time){
    return new Promise(function(resolve){
        return setTimeout(function(){ 
                    return resolve(time + 200)
               },time);
    })
}

function first(time){
    console.log('第一次延迟了' + time );
    return timeout(time);
}
function second(time){
    console.log('第二次延迟了' + time );
    return timeout(time);
}
function third(time){
    console.log('第三次延迟了' + time );
    return timeout(time);
}

function start(){
    console.log('START');
    const time1 = 500;
    first(time1).then(time2 => second(time2) )
                .then(time3 => third(time3)  )
                .then(res => {
                              console.log('最后一次延迟' + res );
                              console.timeEnd('END');
                             })
};
start();

Таким образом, разрешение выполняется путем обратного вызова цепочки.

//打印结果

START
第一次延迟了500
第二次延迟了700
第三次延迟了900
最后一次延迟1100
END

Как насчет использования async/await?

async function start() {
    console.log('START');
    const time1 = 500;
    const time2 = await first(time1);
    const time3 = await second(time2);
    const res = await third(time3);
    console.log(`最后一次延迟${res}`);
    console.log('END');
}
start();

добился того же эффекта. Но есть проблема, еслиawaitПри выполнении возникает ошибка

async function start() {
    console.log('START');
    const time1 = 500;
    const time2 = await first(time1);
    const time3 = await Promise.reject(time2);
    const res = await third(time3);
    console.log(`最后一次延迟${res}`);
    console.log('END');
}
start();

После возврата reject следующий код не выполняется, поэтому посмотрите пример:

let last;
async function throwError() {  
    await Promise.reject('error');    
    last = await '没有执行'; 
}
throwError().then(success => console.log('成功', last))
            .catch(error => console.log('失败',last))

`фактически`

asyncФункция не сложная, сложность в обработке ошибок.

Вышеупомянутая функция, выполненная дляawaitПосле устранения ошибки выполнение останавливается, в результате чегоlastОшибки назначения нет.

Если в `async` есть несколько функций ожидания, если какая-либо из них выдает исключение или сообщает об ошибке, это приведет к остановке выполнения функции, прямому `отклонению`;

Как с этим бороться, можно использоватьtry/catch, когда вы сталкиваетесь с функцией, вы можете выдать ошибку и продолжить выполнение.

let last;
async function throwError() {  
    try{  
       await Promise.reject('error');    
       last = await '没有执行'; 
    }catch(error){
        console.log('has Error stop');
    }
}
throwError().then(success => console.log('成功', last))
            .catch(error => console.log('失败',last))

В этом случае можно продолжать выполнение.

Приходи и тренируйся 🌰

function testSometing() {
    console.log("testSomething");
    return "return testSomething";
}

async function testAsync() {
    console.log("testAsync");
    return Promise.resolve("hello async");
}

async function test() {
    console.log("test start...");

    const testFn1 = await testSometing();
    console.log(testFn1);

    const testFn2 = await testAsync();
    console.log(testFn2);

    console.log('test end...');
}

test();

var promiseFn = new Promise((resolve)=> { 
                    console.log("promise START...");
                    resolve("promise RESOLVE");
                });
promiseFn.then((val)=> console.log(val));

console.log("===END===")

Результаты

Давайте проанализируем это шаг за шагом

во-первыхtest()распечататьtest start...

потомtestFn1 = await testSomething();, он будет выполняться первымtestSometing()Эта функция печатает "testSometing"Нить.

testAsync()возврат после выполненияresolve,послеawaitПозволит потоку перейти к выполнению последнего,курокpromiseFnраспечатать"promise START...".

Затем возвращаемое обещание будетresolve("promise RESOLVE")Поместите его в очередь обещаний (очередь заданий обещаний) и продолжайте печатать"===END===".

После того, как этот раунд выполнения цикла событий закончится, он вернется кasyncв функции (test()функция), прежде чем ждатьawaitвозвращаемое значение последнего выражения, потому чтоtestSometing()нетasyncфункция, поэтому она возвращает строку "return``testSometing".

test()Функция продолжает выполняться до тех пор, покаtestFn2(), выпрыгнуть сноваtest()функция, которая печатает "testAsync", в этот момент цикл событий поступает в очередь промисов и выполняетсяpromiseFn.then((val)=> console.log(val));распечатать"promise RESOLVE".

После этого, как и раньше, вернитесь к тестовой функции, чтобы продолжить выполнение.console.log(testFn2)возвращаемое значение, печатает "hello async".

Наконец напечатайте "test end...".

добавь кое-что, пустьtestSomething()статьasync

async function testSometing() {
    console.log("testSomething");
    return "return testSomething";
}

async function testAsync() {
    console.log("testAsync");
    return Promise.resolve("hello async");
}

async function test() {
    console.log("test start...");

    const testFn1 = await testSometing();
    console.log(testFn1);

    const testFn2 = await testAsync();
    console.log(testFn2);

    console.log('test end...');
}

test();

var promiseFn = new Promise((resolve)=> { 
                    console.log("promise START...");
                    resolve("promise RESOLVE");
                });
promiseFn.then((val)=> console.log(val));

console.log("===END===")

Результаты

По сравнению с предыдущим примером установлено, чтоpromiseFn.then((val)=> console.log(val)); доconsole.log(testFn1)воплощать в жизнь.

Причина в том, что текущая версия асинхронной функции будет разрешена с помощью await,

function testSometing() {
    console.log("testSomething");
    return "return testSomething";
}
console.log(Object.prototype.toString.call(testSometing)) // [object Function]
console.log(Object.prototype.toString.call(testSometing())) // [object String]

async function testSometing() {
    console.log("testSomething");
    return "return testSomething";
}
console.log(Object.prototype.toString.call(testSometing)) // [object AsyncFunction]
console.log(Object.prototype.toString.call(testSometing())) // [object Promise]

testSomething()Это уже асинхронная функция, и возвращаемый объект Promise должен дождаться его разрешения, а затем поместить текущий Promise в очередь, а затем сначала очистить воздушный стек, чтобы он «выпрыгнул» из функции test(). для выполнения последующего кода,Только после этого обещание начинает выполняться.

возобновить

Сегодня 2019-11-06 12:03:46, и получил отзывы от нескольких диггеров. Время выполнения последнего примера не соответствует результатам существующей версии. Причина может быть в том, что Chrome был в течение года и половина с конца статьи.В результате обновления V8, если у вас Opera, другие браузеры, использующие более старую версию ядра Chrome, или перейти наЭтот адресЗагрузите старую версию Chrome, автор использовал Opera для тестирования, и я не нашел соответствующих инструкций в документе о выпуске Chrome V8 или в .

Если в предыдущей версии функция await требовала выполнения 3 тика, то в текущей версии для повышения производительности команда v8 нарушила спецификацию и не соблюдала строгоpromise-resolve-functionsВыполняется 13-й шаг, в результате чего 3 тика уменьшаются на 2.оригинальный

В Node 11 этот механизм был унифицирован с браузером.На первый взгляд вы можете понять, что Promise, возвращаемый await AsyncFunction, является синхронной задачей.

позже

Все больше и больше людей изучают async/await, который считается окончательным решением для асинхронного программирования, но большинство людей не знают, как выполнить этот метод.Я разобрал последовательность выполнения js после await. помочь тебе помочь

  1. — это новый способ написания асинхронного кода. Предыдущим решением для асинхронного кода были обратные вызовы и обещания.
  2. Построен на промисах, и подобные промисы не блокируют.
  3. async/await делает асинхронный код более похожим на синхронный. Вот в чем его сила.

использованная литература:Понимание async/await в JavaScript