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

异步对象:

// 异步函数a
var a = function () {
return new Promise(function (resolve, reject) {
console.log("a")
setTimeout(function () {
resolve('a')
}, )
})
} // 异步函数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')
}, )
})
}

注意: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方法

promise顺序执行,返回结果存放在数组的更多相关文章

  1. reduce + Promise 顺序执行代码

    本文地址: http://www.cnblogs.com/jasonxuli/p/4398742.html 下午的太阳晒得昏昏沉沉,和上周五一样迷糊,看一段代码半天没看明白,刚才不知不觉眯了几分钟,醒 ...

  2. 超耐心地毯式分析,来试试这道看似简单但暗藏玄机的Promise顺序执行题

    壹 ❀ 引 就在昨天,与朋友聊到JS基础时,她突然想起之前在面试时,遇到了一道难以理解的Promise执行顺序题.由于我之前专门写过手写promise的文章,对于部分原理也还算了解,出于兴趣我便要了这 ...

  3. 8张图让你一步步看清 async/await 和 promise 的执行顺序

    摘要: 面试必问 原文:8张图帮你一步步看清 async/await 和 promise 的执行顺序 作者:ziwei3749 Fundebug经授权转载,版权归原作者所有. 为什么写这篇文章? 说实 ...

  4. ES6 Promise 让异步函数顺序执行

    应用 ES6 的 内置对象 Promise, 让异步函数 按顺序执行的例子 如下: 上边 是四个用Promise 处理过的 异步执行的函数: fn1.fn2.fn3.fn4 下面,让其按顺序执行 如下 ...

  5. Promise 异步函数顺序执行

    可以满足需求,且使用方法和Promise.all统一 var a = function() { return new Promise(function(resolve, reject) { setTi ...

  6. promise实现图片按照指定的加载顺序执行

    promise实现图片按照指定的加载顺序执行,先加载第二张,再加载第一张,最后加载第三张 <!DOCTYPE html> <html lang="en"> ...

  7. js函数整合队列顺序执行插件

    前言 在日常开发中,也许我们会遇到这样的一个问题.我们利用[发布订阅模式](如果不了解的可以直接访问此链接www.cnblogs.com/xiaoxiaokun- )去执行[发布]事件时,遇到函数内部 ...

  8. js多个异步请求,按顺序执行next

    在js里面,偶尔会遇见需要多个异步按照顺序执行请求,又不想多层嵌套,,这里和promise.all的区别在于,promise或者Jquery里面的$.when 是同时发送多个请求,一起返回,发出去的顺 ...

  9. js的并行加载以及顺序执行

    重新温习了下这段内容,发现各个浏览器的兼容性真的是搞大了头,处理起来很是麻烦. 现在现总结下并行加载多个js的方法: 1,对于动态createElement('script')的方式,对所有浏览器都是 ...

随机推荐

  1. HBase 架构与工作原理5 - Region 的部分特性

    本文系转载,如有侵权,请联系我:likui0913@gmail.com Region Region 是表格可用性和分布的基本元素,由列族(Column Family)构成的 Store 组成.对象的层 ...

  2. 解决Linux关闭SSH,终端后运行程序终止问题(包括后台)

    问题描述: 每次SSH到服务器上,然后运行了一个自己写的服务端程序,比如 ./myserver.sh ,然后关闭ssh或者终端之后,发现服务不能访问. 简要分析下: 根据   这篇博文  的提示,ss ...

  3. css中对position的几种定位方式的最佳诠释

    关于元素的position定位的理解,牛客网的hardy给出了一个比较好的理解: 在html中网页可以看成一个立体的空间,一个完整的页面是由很多个页面堆积形成的,如上图所示   CSS中Positio ...

  4. three.js:Failed to execute 'texImage2D' on 'WebGLRenderingContext解决方案

    three.js加载图片时,出现Failed to execute 'texImage2D' on 'WebGLRenderingContext .Tainted canvases may not b ...

  5. Python学习---字符串操作

    ### 截取字符串然后拼接 str = "Hello World!" str2 = str[:6] + "tyche !" print(str2) ===> ...

  6. 【BZOJ1835】基站选址(线段树)

    [BZOJ1835]基站选址(线段树) 题面 BZOJ 题解 考虑一个比较暴力的\(dp\) 设\(f[i][j]\)表示建了\(i\)个基站,最后一个的位置是\(j\)的最小代价 考虑如何转移\(f ...

  7. 如何在Eclipse 中查看(如Objects)的源代码

    今天突然想看Objects的源码,结果失败了,总结了一下,贴出来. 一般查看源码的流程: 使用快捷键Ctri+Shit+T出现Open Type的对话框,在里面直接输入类名,回车就行: 在Eclips ...

  8. 单点登录(九)-----遇到问题-----FileNotFoundException: class path resource-UsernamePasswordWrapperAuthenticatio

    运行cas server 项目时 报错 FileNotFoundException: class path resource-UsernamePasswordWrapperAuthenticatio ...

  9. es6字符串新特性

    转: 字符串的扩展 修改教程 上一节 : 变量的解构赋值 下一节 : 正则的扩展 字符串的扩展 ES6 加强了对 Unicode 的支持,并且扩展了字符串对象. 字符的 Unicode 表示法 Jav ...

  10. Qt 查找功能

    版权声明 该文章原创于Qter开源社区(www.qter.org),作者yafeilinux,转载请注明出处!     导语 这一篇我们来加上查找菜单的功能.因为要涉及Qt Creator的很多实用功 ...