随着现代浏览器的不断发展, 相信大家渐渐对 ES6 中的 Promise 已经有很多的使用了, 其中对 Promise.all 估计也用的很多. Promise.all 就是并行执行多个任务, 然后在所有任务成功后触发 then 里面的内容, 或者任意一个任务失败后触发 catch 里面的内容.
虽然 Promise.all 非常好用, 但它也不是适合所有的场景, 最常见的就是有些场景是需要串行的, 一个任务列表要按顺序依次循环执行, 任意一个失败就不触发下面的任务. 那要实现这样的功能能怎么写呢?
最简单的就是一个个写
- var a = ()=>{return new Promise((resolve, reject) => {
- setTimeout(resolve, 1000);
- });}
- var b = ()=>{return new Promise((resolve, reject) => {
- setTimeout(resolve, 1000);
- });}
- var c = ()=>{return new Promise((resolve, reject) => {
- setTimeout(resolve, 1000);
- });}
- a().then(()=>{
- return b()
- }).then(()=>{
- return c()
- }).then(()=>{
- console.log('after 3 sec')
- })
这样写... 真的好挫, 更重要的是, 有时候需要批量处理一个任务, 都是调用同一个函数处理不定长度的数据, 这样写肯定就不行了, 比如要串行请求一串 url. 首先想到的是一个比较绕的方法, 搞个 Promise 链出来, 把下一个任务作为参数传到前一个的 then 中, 如此循环. 这种同一个函数不断循环然后把前一个处理完的值又传到参数里面, 刚好和 Array.reduce 的思想是一致的, 所以可以这么写:
- var urlArr = ['http://www.qq.com','http://www.qq.com','http://www.qq.com'];
- function makaPromiseList(dataArr,handler) {
- return dataArr.reduce((promise, obj) => {
- return promise.then((ret) => {
- return handler(obj);
- })
- }, Promise.resolve())
- }
- var result = [];
- function makeRequest(url){
- return new Promise((resolve,reject)=>{
- $.get(url).success((ret)=>{
- result.push(ret)
- resolve(result)
- }).fail(()=>{
- reject()
- })
- })
- }
- makaPromiseList(urlArr,makeRequest).then((result)=>{
- console.log(result)
- });
老师不给力啊, 理解起来就很绕, 还要在闭包外面定义 result 存数据, 用上 reduce 也觉得有点奇技淫巧, 不太美观啊, 能不能写得更好看点啊.
可以! 说起异步方案, Promise 是很强, 但它还不是最强的, 还有 Promise 的进阶版 -- async/await! 号称 JS 异步的终极解决方案, 真不是盖的, 下面就来看看 async/await 的方案
- var urlArr = ['http://www.qq.com','http://www.qq.com','http://www.qq.com'];
- function makeRequest(url){
- return new Promise((resolve,reject)=>{
- $.get(url).success((ret)=>{
- resolve(ret)
- }).fail(()=>{
- reject()
- })
- })
- }
- async function makaPromiseList(dataArr,handler){
- var result = [];
- for(let item of dataArr){
- var ret = await handler(item);
- result.push(ret);
- }
- return result;
- }
- makaPromiseList(urlArr,makeRequest).then((ret)=>{
- console.log(ret)
- });
一个 for 循环解决串行异步问题, 没有回调没有嵌套看起来瞬间舒服多了~
来源: https://juejin.im/entry/5bece61ef265da613d7ba2dd