Keep

Async/Await

12/20/2017, 8:00:00 AM 3 min read

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)
Tag:
JavaScript

@read2025, 生活在北京(北漂),程序员,宅,喜欢动漫。"年轻骑士骑马出城,不曾见过绝望堡下森森骸骨,就以为自己可以快意屠龙拯救公主。"