async/await 语法让开发者用同步的代码写法方式写异步逻辑,扩展之前基于 Promise 的写法。
- 基于 Promise - 比如函数不存在返回值时,默认为返回 Promise.resolve()
- await 会等待后面的 promise 状态到结束 - 卡住,可以理解成同步执行
- 多个 await 存在时,后面的 await 要等待前面的结束
实例
// 下面使用 setTimeout 模拟异步请求
function sleep(n) {
return new Promise(resolve => {
setTimeout(resolve, n * 1000)
})
}
// 部署两个异步接口
function get_ad_data() {
return new Promise((resolve, reject) =>
sleep(1).then(() =>
(config.ad_fail ? reject : resolve)({data: '_ad_data_'})))
}
function get_article_data() {
return new Promise((resolve, reject) =>
sleep(2).then(() =>
(config.article_fail ? reject : resolve)({data: '_article_data_'})))
}
// 两个请求之后的处理 - 同步渲染
function renderArticle(article, from) {
console.log('render:', article, from, new Date)
}
function renderAd(ad, from) {
console.log('render_ad:', ad, from, new Date)
}
// 并行
// 基于 Promise 写法
// 代码先同步执行完,等状态到 resolved 时,
// 再执行各种的 then/catch 处理
function application_promise(is_ad) {
let request_article_promise = get_article_data()
// 不考虑 render 异常
let render_article_promise = request_article_promise
.then(article => renderArticle(article, 'promise'))
.catch(e => {
console.log('request.catch', e, 'promise')
return Promise.reject(e)
})
if (is_ad) {
let request_ad_x_promise = get_ad_data()
Promise.all([render_article_promise, request_ad_x_promise]).then(values => {
let [_, ad] = values
renderAd(ad, 'promise')
}).catch(e => {
console.log('catch:', e, 'promise')
})
}
}
// 串行
// await 语法会卡住等待第一个 Promise 状态结束
async function application_async(is_ad) {
var article
try {
article = await get_article_data()
if (article) {
renderArticle(article, 'async')
}
} catch (e) {
console.log('request.catch', e, 'async')
}
// article 异常时,不会再继续 (串行)
if (is_ad && article) {
var ad
try {
ad = await get_ad_data()
if (ad) {
renderAd(ad, 'async')
}
} catch (e) {
console.log('catch:', e, 'async')
}
}
}
// 并行
// 让两个 promise 先行
// 使用 async/await 语法 hold 住状态
async function application_async_ex(is_ad) {
var articlePromise = get_article_data()
var adPromise
if (is_ad) {
adPromise = get_ad_data()
}
var article
try {
let [article, ad] = [
await articlePromise,
await adPromise
]
if (article) {
renderArticle(article, 'async_ex')
if (ad) {
renderAd(ad, 'async_ex')
}
}
} catch (e) {
console.log('request.catch', e, 'async_ex')
}
}
var config = {
ad: true,
ad_fail: false,
article_fail: false
}
application_promise(config.ad)
application_async(config.ad)
application_async_ex(config.ad)