sailei1 / blog

1 stars 0 forks source link

promise 按顺序异步请求,按顺序返回 #46

Closed sailei1 closed 5 years ago

sailei1 commented 5 years ago
/**
 * 按顺序加载异步请求数据(自动执行器)
 * @param {...GeneratorFunction()} args GeneratorFunction函数执行返回值
 * @return {Promise} 返回一个Promise对象p。只要请求出错,就执行p的catch回调,否则执行then回调,回调参数为各个请求结果组成的数组
 */
async function loadDataInOrder (...args) {
  const promises = [...args].map(gen => ({ gen, promise: gen.next().value }))
  const result = []
  let hasErr = false
  for (const { gen, promise } of promises) {
    try {
      result.push(await promise)
    } catch (err) {
      result.push(err)
      hasErr = true
    } finally {
      gen.next(promise)
    }
  }
  if (hasErr) {
    throw result
  }
  return result
}

// 模拟API请求接口
function fetch (api, ms, err = false) {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      err ? reject(`reject-${api}-${ms}`) : resolve(`resolve-${api}-${ms}`)
    }, ms)
  })
}

// 请求接口1
function* load1 () {
  (yield fetch('API1', 3000)).then(function (res) {
    console.log(res)
  }).catch(function (err) {
    console.error(err)
  })
}

// 请求接口2
function* load2 () {
  (yield fetch('API2', 2000, true)).then(function (data) {
    console.log(data)
  }).catch(function (err) {
    console.error(err)
  })
}

// 请求接口3
function* load3 () {
  (yield fetch('API3', 5000)).then(function (data) {
    console.log(data)
  }).catch(function (err) {
    console.error(err)
  })
}

// 按顺序加载异步请求
loadDataInOrder(load1(), load2(), load3()).then(function ([data1, data2, data3]) {
  console.log('ok', data1, data2, data3)
}).catch(function ([err1, err2, err3]) {
  console.error('error', err1, err2, err3)
})

思路: 把请求函数写成迭代器的方式, 然后压到数组里面 然后有await 接收返回参数。