promise顺序执行,返回结果存放在数组

2018-07-19 06:14:14来源:博客园 阅读 ()

遇到面试的一个编程题:三个返回promise对象的异步操作,让你写一个函数可以将这些操作顺序执行,并返回一个数组包含三个异步对象的结果

异步对象:

// 异步函数a
var a = function () {
  return new Promise(function (resolve, reject) {
      console.log("a")
    setTimeout(function () {
      resolve('a')
    }, 1000)
  })
}

// 异步函数b
var b = function () {
  return new Promise(function (resolve, reject) {
      console.log("b")
    resolve('b')
  })
}

// 异步函数c
var c = function () {
  return new Promise(function (resolve, reject) {
      console.log("c")
    setTimeout(function () {
      resolve('c')
    }, 500)
  })
}

注意:promise对象在实例化的时候就会执行,所以函数都是返回promise对象,这样执行函数的时候就会执行promise对象中的内容

我们期望的结果是:

//a
//b
//c
//(3) ["a", "b", "c"]
//done

所以关键是怎么顺序执行promise并把结果一个一个塞到数组里

注意promise对象是不能直接得到resolve传来的结果的,一般的方式是.then里面写resolve的回调函数,所以刚才的需求可以这样写

var mergePromise = async function mergePromise(arr) {
    var mergedAjax = Promise.resolve()
    var data = [] ;
    for(let promise of arr){
        mergedAjax = mergedAjax.then(()=>{
            return promise().then(val=>{
                data.push(val)
            })
        })
    }
    return mergedAjax.then(()=>{
        return data
    })
};

mergePromise([a,b,c]).then(function (data) {
    console.log(data);
    console.log("done");
});

还有这种写法:

var mergePromise = async function mergePromise(arr) {
    var mergedAjax = Promise.resolve()
    var data = [] ;
    for(let promise of arr){
        mergedAjax = mergedAjax.then((val)=>{
            if(val)data.push(val)
            return promise()
        })
    }
    return mergedAjax.then((val)=>{
        data.push(val)
        return data
    })
};

mergePromise(ajaxArray).then(function (data) {
    console.log(data);
    console.log("done");
});

以上两种其实是一个then的链式调用,最后返回收集了异步结果的数组

 

这个需求用asnyc await的写法就比较好看和直观

async function queue(arr) {
  let data = []
  for (let promise of arr) {
    let res = await promise()
    data.push(res)
  }
  return data
}
queue([a, b, c])
  .then(data => {
    console.log(data)
console.log("done");
});

感觉上是返回了一个data数组,应该会报没有.then方法的错误,然而实际上是返回了一个Promise.resolve(data)

至于为什么能将resolve的值抽离出来,是应为await是generator的语法糖,比如一个asnyc函数:

async function myfn(arr) {
let res = await a()
console.log(res)
res = await b()
console.log(res)
res = await c()
console.log(res)
}


myfn([a,b,c])

其实等价于自动执行的generator函数

function spawn(genF) {
  return new Promise(function(resolve, reject) {
    const gen = genF();
    function step(nextF) {

      let next;
      try {
        next = nextF();
      } catch(e) {
        return reject(e);
      }
      if(next.done) {
        return resolve(next.value);
      }
      Promise.resolve(next.value).then(function(v) {
          //Promise.resolve(next.value)中next.value是一个promise对象,比如a()生成的
          //Promise.resolve(arg)中arg是一个promise对象时,将会原封不动返回这个对象
        step(function() { return gen.next(v); });//这里gen.next(v)执行赋值操作 let res = v 也就是为什么async方法能得到promise中resolve的值
        
      }, function(e) {
        step(function() { return gen.throw(e); });
      });
    }
    step(function() { return gen.next(undefined); });
  });
}

function fn(args) {
  return spawn(function* () {
    let res = yield a()
    console.log(res)
    res = yield b()
    console.log(res)
    res = yield c()
    console.log(res)
  });
}

fn()

 

最后说一下,如果要让异步操作并发,可以用promise自带的all方法

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:小程序实践(八):验证码倒计时功能

下一篇:用FileReader对象获取图片base64代码并预览