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

最新文章

  1. 【转帖】ActiveX部件不能创建对象的终极解决方案
  2. 动态加载jQuery
  3. IE8控件安装方法
  4. 【bzoj3110】 Zjoi2013—K大数查询
  5. hdu 并查集分类(待续)
  6. win2008修改最大远程桌面连接数
  7. 怎样用HTML5 Canvas制作一个简单的游戏
  8. 使用ServletContextListener和HttpSessionListener两种监听器实现记录当前网站在线人数
  9. windows下npm scripts不能执行的问题
  10. Css实现一个简单的幻灯片效果页面
  11. 201521123083《Java程序设计》第12周学习总结
  12. JS基础四
  13. 关于mysql安装到最后一步老是停留在starting server,显示无响应
  14. UNIX环境高级编程——I/O多路转接(select、pselect和poll)
  15. C#编译器优化那点事
  16. 简单poi创建execl
  17. Spring源码学习
  18. (转载)CSS3与页面布局学习总结(三)——BFC、定位、浮动、7种垂直居中方法
  19. mysql sql文件批量处理
  20. java注册后缀样式(ajax提示)

热门文章

  1. 用delphi开发activex打印控件
  2. response和request的setCharacterEncoding区别
  3. CSS实现点击改变元素背景色
  4. 文件同步工具 lsyncd2.1.6 安装使用问题
  5. EF 使用 oracle
  6. 使用IDEA远程部署tomcat和调试
  7. 【BZOJ2839】集合计数(容斥,动态规划)
  8. Merge Two Sorted Lists - LeetCode
  9. BZOJ2529 [Poi2011]Sticks 【贪心】
  10. 利用Array Prototype的方法来实现对dom集合的筛选、indexOf、map等功能