构建Promise队列实现异步函数顺序执行

场景

  • 有a、b、c三个异步任务,要求必须先执行a,再执行b,最后执行c
  • 且下一次任务必需要拿到上一次任务执行的结果,才能作操做

思路

  • 咱们须要实现一个队列,将这些异步函数添加进队列而且管理它们的执行,队列具备First In First Out的特性,也就是先添加进去的会被先执行,接着才会执行下一个(注意跟栈做区别)
  • 你们也能够类比一下jQuery的animate方法,添加多个动画也会按顺序执行

解决

  • 模拟3个异步函数javascript

    // 异步函数a
    var a = function () {
      return new Promise(function (resolve, reject) {
        setTimeout(function () {
          resolve('a')
        }, 1000)
      })
    }
    
    // 异步函数b
    var b = function (data) {
      return new Promise(function (resolve, reject) {
        resolve(data + 'b')
      })
    }
    
    // 异步函数c
    var c = function (data) {
      return new Promise(function (resolve, reject) {
        setTimeout(function () {
          resolve(data + 'c')
        }, 500)
      })
    }
  • 解决方法一(使用then链式操做)php

    • 特色:能够知足需求,可是书写比较繁琐
    • 代码html

      //链式调用
      a()
        .then(function (data) {
          return b(data)
        })
        .then(function (data) {
          return c(data)
        })
        .then(function (data) {
          console.log(data)// abc
        })
  • 方法二(构建队列)java

    • 特色:封装方法,可移植到别处使用
    • 代码web

      // 构建队列
      function queue(arr) {
        var sequence = Promise.resolve()
        arr.forEach(function (item) {
          sequence = sequence.then(item)
        })
        return sequence
      }
      
      // 执行队列
      queue([a, b, c])
        .then(data => {
          console.log(data)// abc
        })
  • 方法三(使用async、await构建队列)api

    • 同方法二,只是显得更高大上点
    • 代码promise

      async function queue(arr) {
        let res = null
        for (let promise of arr) {
          res = await promise(res)
        }
        return await res
      }
      queue([a, b, c])
        .then(data => {
          console.log(data)// abc
        })
  • 顺便说一句,bluebird的Promise.reduce也能够用来顺序执行函数,可是可以使用的场景很是有限,通常用来读取文件信息,而以上给出的方法,无论你在异步函数中作了什么,只要函数最后返回了一个Promise对象,均可以使用异步