прочитать статью перед«6 причин, по которым Async/Await заменяет обещания»,Сейчасasync / awaitграмматика уже естьЭтап 3.
совместимость
- На стороне сервера, в
Node.js 7.6
После версии,async / await
грамматика былаNode.js
поддержка, напримерKoa2
заброшенныйсинтаксис генератора/доходности,Объятиеasync / await
грамматика. - На стороне клиента также можно
Babel
Давайте использовать последние, как нам нравитсяEcmascript
грамматика.
Начните с бизнеса
Лично мне не нравится использовать такой последний синтаксис. Всегда пишите код или обнимайтеPromise
основной. Но так как использованиеasync / await
После грамматики вроде бы есть ощущение зависимости от этой грамматики (похоже на код синхронной блокировки, и не надо быть похожимgenerator
синтаксис для выпуска вручную или использованияco
такая библиотека управления потоком)
Взгляните на эти распространенные бизнес-сценарии ниже:
- Предположим, мы пишем программу для написания вопросов.Эта программа умная (да, она вас понимает).Каждый раз, когда вы заполняете вопрос и отправляете его, сервер будет судить о том, освоили ли вы текущий балл знаний по отправленным вами результатам .., если вы его не осилите, то сервер снова подтолкнет вам следующий вопрос.
- Предположим, мы пишем программу, в которой пользователи вручную идентифицируют изображения, а сервер дает два интерфейса,интерфейс отправкиИспользуется для отправки результата идентификации предыдущего изображения, только еслиинтерфейс отправкиОтправка прошла успешно, можно перейти к запросуинтерфейс следующий, чтобы запросить ссылку на следующее изображение.
const requestSubmit = () => {
return new Promise((resolve, reject) => {
$.ajax({
url: '/submit',
success: (data) => {
resolve(data);
},
error: (err) => {
reject(err);
},
});
});
};
const requestNext = () => {
return new Promise((resolve, reject) => {
$.ajax({
url: '/next',
success: (data) => {
resolve(data);
},
error: (err) => {
reject(err);
},
});
});
};
Если мы используемPromise
грамматика:
requestSubmit()
.then((data) => {
// dosomething
return requestNext();
})
.then((data) => {
// dosomething
})
.catch((err) => {
console.log(err);
});
Хотя с помощьюPromise
,catch
только самое последнееPromise.then
ошибка, но на самом деле теперь вы можете отловить каждую ошибку вот так!
не забудьPromise.then
Второй параметр:
requestSubmit()
.then((data) => {
// dosomething
return requestNext();
}, (err) => {
console.log(err);
})
.then((data) => {
// dosomething
},(err) => {
console.log(err);
});
Теперь есть проблема, сервер может проверить статус входа пользователя, правильность параметров и т.д. Если статус входа пользователя недействителен, первыйajax
просьба, все равно пойдетsuccess
Обратный вызов не вызовет ошибку, вам все равно придется изменить его вручную в это время.requestSubmit
функция.
также,Promise.catch
Метод перехватывает только самую последнюю ошибку, поэтому неизвестно, где именно возникла ошибка.
Такие как:
const makeRequest = () => {
return callAPromise()
.then(() => callAPromise())
.then(() => callAPromise())
.then(() => callAPromise())
.then(() => callAPromise())
.then(() => {
throw new Error("oops");
})
}
makeRequest()
.catch(err => {
console.log(err);
// output
// Error: oops at callAPromise.then.then.then.then.then (index.js:8:13)
})
Но обратите внимание: исходный текст не полный, мы захватываем его такPromise
Ошибка в порядке:
const makeRequest = () => {
return callAPromise()
.then(() => callAPromise(), err => {
console.log(err);
// output
// Error: oops at callAPromise.then.then.then.then.then (index.js:8:13)
})
.then(() => callAPromise(), err => {
console.log(err);
})
.then(() => callAPromise(), err => {
console.log(err);
})
.then(() => callAPromise(), err => {
console.log(err);
})
.then(() => {
throw new Error("oops");
}, err => {
console.log(err);
});
}
makeRequest();
Если приведенный выше бизнес-сценарий изменить наasync / await
грамматика:
(async function() {
try {
const res1 = await axios.post('/submit');
// dosomething
} catch (err) {
console.log(err);
} finally {
console.log('go next!');
}
try {
const res2 = await axios.get('/next');
// dosomething
} catch (err) {
console.log(err);
} finally {
console.log('done!');
}
})();
Он чувствует себя лучше как с точки зрения перехвата исключений, так и с точки зрения читабельности кода.
Преимущество
На самом деле, большинство из них подхватывают эту статью:
лаконичный
использоватьasync / await
Значительная экономия кода. нам не нужно писать.then
, не нужно писать анонимную обработку функцийPromise
изresolve
значение, нет необходимости определять избыточные переменные данных и избегать вложенного кода. Эти небольшие преимущества быстро складываются, что станет более очевидным в следующих примерах кода.
обработка ошибок
async / await
Позволятьtry / catch
Можно обрабатывать как синхронные, так и асинхронные ошибки. В следующихPromise
В примереtry / catch
Не выдерживаюJSON.parse
ошибка, потому что это вPromise
середина. нам нужно использовать.catch
, поэтому код обработки ошибок очень избыточен. И в нашем реальном производстве код будет более сложным.
const makeRequest = () => {
try {
getJSON()
.then(result => {
// JSON.parse可能会出错
const data = JSON.parse(result)
console.log(data)
})
// 取消注释,处理异步代码的错误
// .catch((err) => {
// console.log(err)
// })
} catch (err) {
console.log(err)
}
}
использоватьasync / await
если,catch
может справитьсяJSON.parse
ошибка:
const makeRequest = async () => {
try {
// this parse may fail
const data = JSON.parse(await getJSON())
console.log(data)
} catch (err) {
console.log(err)
}
}
Условные операторы
Об этом также сказано выше:
В следующем примере вам нужно получить данные, а затем решить, возвращаться ли напрямую или продолжать получать дополнительные данные в соответствии с возвращенными данными.
const makeRequest = () => {
return getJSON()
.then(data => {
if (data.needsAnotherRequest) {
return makeAnotherRequest(data)
.then(moreData => {
console.log(moreData)
return moreData
})
} else {
console.log(data)
return data
}
})
}
Эти коды - головная боль, чтобы смотреть на них. вложенные (6 уровней), скобки,return
Заявления могут легко потеряться, им просто нужно передать окончательный результат в самый внешнийPromise
.
В приведенном выше коде используетсяasync / await
Написание может значительно улучшить читаемость:
const makeRequest = async () => {
const data = await getJSON()
if (data.needsAnotherRequest) {
const moreData = await makeAnotherRequest(data);
console.log(moreData)
return moreData
} else {
console.log(data)
return data
}
}
медиана
Вы, вероятно, сталкивались со сценарием, в котором вызывается promise1, вызывается promise2 с результатом, возвращаемым promise1, а promise3 вызывается с результатом обоих. Ваш код, скорее всего, будет выглядеть так:
const makeRequest = () => {
return promise1()
.then(value1 => {
return promise2(value1)
.then(value2 => {
return promise3(value1, value2)
})
})
}
еслиpromise3
ненужныйvalue1
, легко конвертироватьpromise
Вложенное мощение. Если вы терпеть не можете вложенность, вы можете поставитьvalue 1 & 2
вставитьPromise.all
Чтобы избежать глубокой вложенности:
const makeRequest = () => {
return promise1()
.then(value1 => {
return Promise.all([value1, promise2(value1)])
})
.then(([value1, value2]) => {
return promise3(value1, value2)
})
}
стек ошибок
Здесь вы можете увидеть реальный бизнес-пример выше.
отладка
async/await
Может упростить отладку кода. 2 причины сделать отладкуPromise
становится очень больно:
- Вы не можете устанавливать точки останова в стрелочных функциях, которые возвращают выражения
- если ты
.then
Чтобы установить точки останова в блоках кода, используйтеStep Over
Ярлыки, отладчик не переходит к следующему.then
, так как он будет пропускать только асинхронный код. использоватьawait / async
, вам больше не нужно столько стрелочных функций, так что вы можете пропустить, например, отладку синхронного кодаawait
утверждение.