zoukankan      html  css  js  c++  java
  • promise顺序执行,返回结果存放在数组

    遇到面试的一个编程题:三个返回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方法

  • 相关阅读:
    Python学习(十六)内置函数,递归
    Python学习(十五)json串使用,不固定参数,关键词参数
    Python学习(十四)常量,局部变量,全局变量
    python学习(十三)函数
    python学习(十二)模块
    Python学习(十一)文件指针,文件操作练习,修改文件
    mongodb聚合
    mongodb
    软件测试需要学习哪些课程
    Jmeter的使用和监控分析
  • 原文地址:https://www.cnblogs.com/maskmtj/p/9324669.html
Copyright © 2011-2022 走看看