JavaScript 编写异步代码 
回调函数 
事件监听 
发布订阅,消息中心 
Promise/A+ 
Generator 
async/await 
Thunk 
 
Promise 示例 Promise 值具有穿透性,穿透一个没有用的 .then() 直接到达 一个有用的 .then()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 let  p1 = new  Promise ((resolve,reject ) =>  {  resolve(1 ) }) p1.then()   .then(value  =>     console .log(value);     return  value + 1    }).then(value  =>     console .log(value);   }) let  p2 = Promise .resolve(1 );p2.then(v  =>1  })   .then(v  =>console .log(v)}); let  p3 = Promise .resolve(1 );p3.then(v  =>1 ); p3.then(v  =>console .log(v)); let  p4 = Promise .resolve(1 );p4.then(v  =>   return  new  Promise ((resolve,reject ) =>  {     setTimeout (() =>  resolve(2 ))   }) }).then(v  =>console .log(v)); let  p1 = new  Promise ((resolve , reject ) =>  {  reject(new  Error  ('some wrong' )) }) let  p2 = p1.then(  value => { console .log(value) },   reason => { console .log(reason.message) } ) p2.then(()=> {   throw  new  Error ('something wrong 1' ) }).catch(reason  =>   console .log(reason.message) }) Promise .reject(new  Error ('error' )))  .catch(reason  =>     console .log(reason.message);     return  `${reason.message}  occured`    }).then(v  =>console .log(v)); function  sleep (duration )  return  new  Promise ((resolve,reject ) => {     setTimeout (() =>  {resolve(),duration})   }) } async  function  run (  const  start = Date .now();   await  sleep(1000 );   await  sleep(2000 );   await  sleep(3000 );   console .log(Date .now() - start) } run() function  run1 (  const  start = Date .now();   return  Promise .resolve()     .then(function (return  sleep(1000 )})     .then(function (return  sleep(2000 )})     .then(function (return  sleep(3000 )})     .then(function (console .log(Date .now() - start)}) } run1(); 
实现 Promise 需要注意 
符合 Promise/A+ 标准 
不暴露过多的函数和变量 
Promise 状态只能修改一次 
then() 和 catch 需要异步执行 
then 能够实现链式调用 
then 返回新的 Promise 
then 值能够穿透 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 const  PENDING = 0 ;const  FULFILLED = 1 ;const  REJECTED = 2 ;class  Promise    constructor (fn )           this ._state = PENDING;     this ._data = null ;     this ._onFulfilledCallbacks = [];     this ._onRejectedCallbakcs = [];     run(this ,fn);   }   static  deferred (){     const  dfd = {}     dfd.promise = new  promise ((resonlve,reject ) =>  {       dfd.resolve = resolve;       dfd.reject = reject;     })     return  dfd;   }   then (onFulfilled, onRejected )     if (typeof  onFulfilled !== 'function' ){       onFulfilled = function (data )         return  data       }     }     if (typeof  onRejected !== 'function' ){       onRejected = function (reason )         throw  reason       }     }     let  promise2;     if (this ._state === FULFILLED){       promise2 = new  Promise ((resolve,reject  ) => {         setTimeout (()=> {           try {             const  x = onFulfilled(this ._data)             resolvePromise(promise2,x,resolve,reject)           }catch (e){             reject(e);           }         })       })     }else  if (this ._state === REJECTED){       promise2 = new  Promise ((resolve,reject  ) => {         setTimeout (()=> {           try {             const  x = onRejected(this ._data)             resolvePromise(promise2,x,resolve,reject)           }catch (e){             reject(e);           }         })       })     }else  if (this ._state === PENDING){       promise2 = new  Promise ((resolve,reject )=> {         this ._onFulfilledCallbacks.push(data  =>           try {             const  x = onFulfilled(data)             resolvePromise(promise2,x,resolve,reject)           }catch (e){             reject(e)           }         })         this ._onRejectedCallbakcs.push(reason  =>           try {             const  x = onRejected (reason)             resolvePromise(promise2,x,resolve,reject)           }catch (e){             reject(e)           }         })       })     }   }   return  promise2 } catch (onRejected){  return  this .then(undefined ,onRejected) } function  resolvePromise  (promise2,x,resolve,reject )  if (x instanceof  Promise ){     return  x.then(resolve,reject);   }else {     resolve(x)   } } function  run  (promise,fn )  try {     fn(       data => {                  resolve(promise,data)       },       reason => {                  reject(promise,reason)       }     )   }catch (e){          reject(promise,e)   } } function  resolve (promise,data )      if (data instanceof  Promise ){     return  data.then(       d => { resolve (promise,d)},       r => { reject (promise,r)}     )   }   if (promise._state !== PENDING){     callback(data)   }   setTimeout (()=> {     promise._state = FULFILLED;     promise._data = data;     for (let  callback of  promise._onFulfilledCallbacks) {       callback(data)     }   }) } function  reject (promise,reason )   if (promise._state !== PENDING){     return    }   setTimeout (()=> {     promise_state = REJECTED     promise_data = reason     for  (let  callback of  promise__onRejectedCallbakcs){       callback(reason   )     }   }) } module .exports = Promise ;
校验 是否符合 promise 规范
promises-aplus-tests
Promise 是什么 按照用途来解释 
主要用于异步计算。 
可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果。 
可以在对象之间传递和操作 Promise,帮助我们处理队列。 
 
为什么会有 Promise JavaScript 包含大量异步操作
JavaScript 为检查表单而生。
为什么异步操作可以避免界面冻结 同步问题:按顺序执行,按顺序完成。
异步:完成顺序和执行顺序无关。
异步操作的常见语法 事件监听与响应:
1 2 3 4 5 6 7 8   document .getElementById("start" ).addEventListener("click" , start, false );   function  start (        }   $("#start" ).on("click" , start); 
异步操作的常见语法
1 2 3 4 5 6 7 8 9 10 $.ajax("http://baidu.com" , {   success: function  (res )         }, }); $(function  (    }); 
浏览器中的 JavaScript 
异步操作以事件为主 
回调主要出现在 Ajax 和 File API 
 
Node.js 的出现 对异步的依赖进一步加剧了
无阻赛高并发,是 Node.js 的招牌。 
异步操作是其保障。 
大量操作依赖回调函数。 
 
异步回调的问题 
嵌套层次很深,难以维护 
无法正常使用 return  和 throw  
无法正常检索堆栈信息 
多个回调之间难以建立联系 
 
Promise 详解 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 new  Promise (     function  (resolve, reject )           resolve();      reject();    } ).then(   function  A (        },   function  B (        } ); 
Promise 是一个代理对象,它和原先要进行的操作并无关系。
Promise 有 3 个状态 pending [待定] 初始状态
Promise 状态发生改变,就会触发 .then() 里的响应函数处理后续步骤。
范例
1 2 3 4 5 6 7 new  Promise ((resolve ) =>  {  setTimeout (() =>  {     resolve("hello" );   }, 2000 ); }).then((value ) =>  {   console .log(value + "world" ); }); 
两步执行范例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 new  Promise ( resolve  =>  setTimeout (()=> {     resolve('hello' );   },2000 ); }).then( value  =>   console .log(value);   return  new  Promise ( resolve  =>     setTimeout (() =>  {       resolve('world' );     },2000 );   }); }).then( value  =>   console .log( value + 'world' ); }) 
对已完成的 promise 执行 1 2 3 4 5 6 7 8 9 10 11 12 13 let  promise = new  Promise (resolve  =>  setTimeout (() =>  {     console .log('the promise fulfilled' );     resolve('hello,world' );   },1000 ) }) setTimeout (()=> {  promise.then( value  =>     console .log(value);   }) },3000 ) 
then 里不返回 promise 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 new  Promise ( resolve  =>  setTimeout (() => {     resolve('hello' );   },2000 ); }).then(value  =>   console .log(value);   console .log('everyone' );   (function  (     return  new  Promise (resolve  =>       setTimeout (()=> {         console .log('Mr.Laurence' );         resolve(' Merry Xmas ' );       },2000 )     });   }());   return  false ; }).then( value  =>   console .log(value + ' world' ); }) 
.then() 
.then() 接受两个函数作为参数,分别代表 fulfilled 和 rejected 
.then() 返回一个新的 Promise 实例,所以它可以链式调用 
当前面的 Promise 状态改变时,.then() 根据其最终状态,选择特定的状态响应函数执行 
状态响应函数可以返回新的 Promise,或其他值 
如果返回新的 Promise,那么下一级 .then()  会在新 Promise 状态改变之后执行。 
如果返回其他任何值,则会立刻执行下一级 .then()  
 
.then()里有 .then()的情况 
因为 .then()  返回的还是 Promise 实例。 
会等里面的 .then() 执行完,再执行外面的。 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 console .log('start' )new  Promise ( resolve  =>  console .log('Step 1' );     setTimeout (() => {       resolve('1000' );     },1000 );   }).then(value  =>     return  new  Promise ( resolve  =>       console .log('Step 1-1' );       setTimeout (()=> {         resolve(110 );       },1000 )     }).then( value  =>       console .log('Step 1-2' );       return  value;     }).then(value  =>       console .log('Step 1-3' );       return  value;     })   }).then( value  =>     console .log(value);     console .log('Step 2' );   }) 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 console .log('start' )new  Promise ( resolve  =>  console .log('Step 1' );     setTimeout (() => {       resolve('1000' );     },1000 );   }).then(value  =>     return  new  Promise ( resolve  =>       console .log('Step 1-1' );       setTimeout (()=> {         resolve(110 );       },1000 )     })   }).then( value  =>       console .log('Step 1-2' );       return  value;     }).then(value  =>       console .log('Step 1-3' );       return  value;     }).then( value  =>     console .log(value);     console .log('Step 2' );   }) 
下面 Promise 的区别 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 doSomething().then(function (   return  doSomethingElse() }); doSomething().then(function (   doSomethingElse() }); doSomething().then(   doSomethingElse() ); doSomething().then(   return  doSomethingElse ); 
错误处理 Promise 会自动捕获内部异常,并交给 rejected 响应函数处理。
reject(‘错误信息’).then(null,message =>{}) 
throw new Error(‘错误信息’).catch( message => {}) 
 
推荐第二种,更加清晰好读,并且可以捕获前面的错误。
1 2 3 4 5 6 7 8 9 new  Promise ( resolve  =>  setTimeout (()=> {     throw  new  Error ('bye' );   },2000 ); }).then( value  =>   console .log(value + 'world' ); }).catch( error  =>   console .log( 'Error:' ,error.message ) }) 
1 2 3 4 5 6 7 8 9 new  Promise ( (resolve,reject ) => {  setTimeout (()=> {     reject('bye' );   },2000 ); }).then( value  =>   console .log(value + 'world' ); },value  =>   console .log('Error' ,value); }) 
.catch() + .then() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 new  Promise (resolve  =>  setTimeout (()=> {     resolve();   },1000 ) }).then(()=> {   console .log('start' );   throw  new  Error ('test error' ); }).catch( err  =>   console .log('I catch ' ,err);    }).then(()=> {   console .log('arrive here' ); }).then(()=> {   console .log('...and here' ); }).catch( err  =>   console .log('No,I catch' ,err); }) 
注意:
  强烈建议在所有队列最后都加上 .catch(),以避免漏掉错误处理造成意想不到的问题。
 
1 2 3 4 5 6 doSomething()   .doAnotherThing()   .doMoreThing()   .catch( err  =>     console .log(err);   }) 
Promise 常用函数 Promise.all() 批量执行
Promise.all([p1,p2,p3,…]) 用于将多个 Promise 实例,包装成一个新的 Promise 实例 
返回的实例就是普通 Promise 
接收一个数组作为参数。 
数组里可以是 Promise 对象,也可以是别的值,只有 Promise 会等待状态改变。 
当所有子 Promise 都完成,该 Promise 完成,返回值是全部值的数组 
有任何一个失败,该 Promise 失败,返回值是第一个失败的子 Promise 的结果。 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 Promise .all([1 ,2 ,3 ]).then( all  =>  console .log('1: ' ,all);   return  Promise .all([function (     console .log('ooxx' );   },'xxoo' ,false ]); }).then(all  =>   console .log('2: ' ,all);   let  p1 = new  Promise ( resolve  =>     setTimeout (()=> {       resolve('I\'m P1' );     },1500 )   })   let  p2 = new  Promise ( resolve  =>     setTimeout (()=> {       resolve('I\'m P2' );     },1450 )   })   return  Promise .all([p1,p2]); }).then( all  =>   console .log('3: ' ,all);   let  p1 = new  Promise ( resolve  =>     setTimeout (() =>  {       resolve('I\'m P1' );     },1500 )   })   let  p2 = new  Promise ( (resolve,reject )  => {     setTimeout (() =>  {       reject('I\'m P2' );     },1000 )   })   let  p3 = new  Promise ( (resolve,reject ) => {     setTimeout (() =>  {       reject('I\'m P3' );     },3000 )   }) }).then( all  =>   console .log('all' ,all); }).catch(err  =>   console .log(err); }) 
Promise.add() 和 .map() 连用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 const  fs = require ('fs' );const  path = require ('path' );const  FileSystem = require ('./FileSystem' );function  findLargest (dir )       return  FileSystem.readDir(dir, 'utf-8' ).then( files  =>     return  Promise .all( files.map( file  =>       return  new  Promise  (resolve  =>         fs.stat(path.join(dir, file), (err, stat ) =>  {           if  (err) throw  err;             if  (stat.isDirectory()) {               return  resolve({                 size: 0                });             }             stat.file = file;               resolve(stat);             });           });         }));       }).then( stats  =>         let  biggest = stats.reduce( (memo, stat ) =>  {         if (memo.size < stat.size) {           return  stat;         }           return  memo;         });           return  biggest.file;         })       } 
实现队列 使用 .forEach()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 function  queue (things )  let  promise = Promise .resolve();   things.forEach( thing  =>     promise = promise.then(()=> {       return  new  Promise ( resolve  =>         doThing(thing,()=> {           resolve();         });       })     })   })   return  promise; } queue('lots' ,'of' ,'things' ,...) 
常见错误:
没有把 .then()产生的新 Promise 实例赋给 promise,没有生成队列。
 
使用 .reduce()
1 2 3 4 5 6 7 8 9 10 11 12 function  queue (things )  return  things.reduce((promise,thing ) =>  {     return  promise.then(() =>  {       return  new  Promise ( resolve  =>         doThing(thing,()=> {           resolve();         });       });     });   },Promise .resolve()); } queue('lots' ,'of' ,'things' ,...) 
常见错误:
Promise 实例创建之后,会立刻运行执行器代码,所以这个也无法达成队列的效果。
 
半成品爬虫 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 let  url = ['http://blog.meathill.com/' ];function  fetchAll (urls )     return  urls.reduce((promise, url ) =>  {         return  promise.then( () =>  {           return  fetch(url);         });     }, Promise .resolve()); } function  fetch (url )     return  spider.fetch(url)         .then( content  =>           return  saveOrOther(content);         })         .then( content  =>           let  links = spider.findLinks(content);           return  fetchAll(links);         }); } fetchAll(url); 
Promise.resolve() 返回一个 fulfilled  的 Promise 实例,或原始 Promise 实例。
参数为空,返回一个状态为 fulfilled 的 Promise 实例。 
参数是一个跟 Promise 无关的值,同上,不过 fulfilled   响应函数会得到这个参数 
参数为 Promise 实例,则返回该实例,不做任何修改 
参数为 thenable,立刻执行它的 .then()。 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Promise .resolve().then( (value ) =>  {  console .log('Step 1' , value);   return  Promise .resolve('Hello' ); }).then( value  =>   console .log(value,'World' );   return  Promise .resolve(new  Promise ( resolve  =>     setTimeout (()=> {       resolve('Good' );     },2000 );   })); }).then( value  =>   console .log(value, 'evening' );   return  Promise .resolve({     then (       console .log(', everyone' );     }   }) }) 
Promise.reject() 返回一个 rejected 的 Promise 实例。
Promise.reject() 不认 thenable
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 let  promise = Promise .reject('something wrong' );promise.then( () =>  {     console .log('it\'s ok' );   }).catch( () =>  {       console .log('no, it\'s not ok' );       return  Promise .reject({       then (         console .log('it will be ok' );       },       catch () {         console .log('not yet' );       }     });   }); 
Promise.race() 类似 Promise.all(),区别在于它有任意一个完成就算完成。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 let  p1 = new  Promise (resolve  =>     setTimeout (() =>  {       resolve('I\'m P1' );   }, 10000 ); }); let  p2 = new  Promise (resolve  =>     setTimeout (() =>  {       resolve('I\'m P2' );   }, 2000 ) }); Promise .race([p1, p2]).then(value  =>  console .log(value); }); 
常见用法:
把异步操作和定时器放在一起 
如果定时器先触发,就认为超时,告知用户 
 
实际开发的 Promise 异步回调包装成 Promise 优点:
可读性更好 
返回的结果可以加入任何 Promise 队列 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 const  fs = require ('fs' );module .exports = {     readDir: function  (path, options )      return  new  Promise ( resolve  =>       fs.readdir(path, options, (err, files ) =>  {         if  (err) {           throw  err;         }         resolve(files);       });     });   },      readFile: function  (path, options )      return  new  Promise ( resolve  =>       fs.readFile(path, options, (err, content ) =>  {         if  (err) {           throw  err;         }         resolve(content);       });     });   } }; const  fs = require ('./FileSystem' );fs.readFile('../README.md' ,'utf-8' ).then(content  =>   console .log(content); }) 
把任意异步操作包装成 Promise 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 let  confirm = popupManager.confirm('您确定么?' );confirm.promise.then(() =>  {    }) .catch(() =>  {    }); class  Confirm    constructor (     this .promise = new  Promise ( (resolve, reject ) =>  {       this .confirmButton.onClick = resolve;       this .cancelButton.onClick = reject;     })   } } 
两步执行 1 2 3 4 5 6 7 8 9 10 11 12 13 let  promise = new  Promise (resolve  =>  setTimeout (() =>  {     console .log('the promise fulfilled' );     resolve('hello,world' );   },1000 ) }) setTimeout (()=> {  promise.then( value  =>     console .log(value);   }) },3000 ) 
实际开发会对请求进行 promise 化,两种情况
返回的数据直接更改值
1 2 3 4 5 6 7 8 9 10 getlist (data )  this .api.getlist(data).then(res =>     this .list = res.data.data;   }) } pullDown (  this .getlist(data); } 
返回数据传递给下个调用的函数
1 2 3 4 5 6 7 8 9 10 11 12 getlist (data )  return  this .api.getlist(data).then(res =>     return  Promise .resolve(res.data.data);   }) } querySearchAsync (  this .getlist(data).then((value )=> {     this .searchlist = value;   }) } 
jQuery jQuery 已经实现了 Promise。1.5 版开始尝试, 3.0版完成的 Promise。
参考 jQuery 的 ajax 实现。
1 2 3 4 5 $.ajax(url,{   dataType: 'json'  }).then(json  =>    }) 
IE 如果需要在 IE 中使用 Promise,有两个选择:
Fetch API Fetch API 是 XMLHttpRequest 的现代化替代方案。
更强大,更友好。 
直接返回一个 Promise 实例。 
response 是一个二进制数据流,需要调用 json()  方法可以转换成 json 数据 
 
1 2 3 4 5 6 7 fetch('some.json' ).then( res  =>   return  res.json() }).then( json  =>    }).catch( err  =>   console .log(err); }) 
async/await ES2017 新增运算符,新的语言元素
赋予 JavaScript 以顺序手法编写异步脚本的能力 
既保留异步运算的无阻塞特性,还继续使用同步写法。 
还能正常使用 return/try/catch。 
 
async/await 仍然需要 Promise!
希望全面了解,请参考 async/await 入门 。
1 2 3 4 async  function  f1 (  const  result = await  resolveAfter2Seconds();   console .log(result); } 
协程 
协程A开始执行。 
协程A执行到一半,进入暂停,执行权转移到协程B。 
(一段时间后)协程B交还执行权。 
协程A恢复执行。 
 
Thunk 参数求值
传名调用,在执行时求值 1 2 3 4 5 6 7 8 9 10 11 12 13 function  f (m )  return  m * 2 ; } f(x + 5 ); var  thunk = function  (  return  x + 5 ; }; function  f (thunk )  return  thunk() * 2 ; } 
在 JavaScript 语言中,Thunk 函数替换的不是表达式,而是多参数函数,将其替换成单参数的版本,且只接受回调函数作为参数。 
1 2 3 4 5 6 7 8 9 10 11 12 fs.readFile(fileName, callback); var  readFileThunk = Thunk(fileName);readFileThunk(callback); var  Thunk = function  (fileName )  return  function  (callback )     return  fs.readFile(fileName, callback);    }; }; 
任何函数,只要参数有回调函数,就能写成 Thunk 函数的形式 。下面是一个简单的 Thunk 函数转换器。
1 2 3 4 5 6 7 8 9 10 11 12 13 var  Thunk = function (fn )  return  function  (   var  args = Array .prototype.slice.call(arguments );     return  function  (callback )       args.push(callback);       return  fn.apply(this , args);     }   }; }; var  readFileThunk = Thunk(fs.readFile);readFileThunk(fileA)(callback); 
Thunkify 模块 生产环境的转换器,建议使用 Thunkify 模块 
Thunk 函数的自动流程管理 控制执行权
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 var  fs = require ('fs' );var  thunkify = require ('thunkify' );var  readFile = thunkify(fs.readFile);var  gen = function * (  var  r1 = yield  readFile('/etc/fstab' );   console .log(r1.toString());   var  r2 = yield  readFile('/etc/shells' );   console .log(r2.toString()); }; var  g = gen();var  r1 = g.next();r1.value(function (err, data )   if  (err) throw  err;   var  r2 = g.next(data);   r2.value(function (err, data )     if  (err) throw  err;     g.next(data);   }); }); function  run (fn )   var  gen = fn();   function  next (err, data )      var  result = gen.next(data);     if  (result.done) return ;     result.value(next);   }   next(); } run(gen); 
Generator Generator 函数是协程在 ES6 的实现,最大特点就是可以交出函数的执行权(即暂停执行)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 function * gen (x )try  {  var  y = yield  x + 2 ;  } catch  (e){   console .log(e); }   return  y; } var  g = gen(1 ); g.next()  g.next()  g.next(2 )  g.throw('出错了' )  
相关资料Promise 入门 √ Generator 函数的含义与用法 √ Thunk 函数的含义和用法 √ fetch polyfill兼容库 彻底搞懂JS事件中的循环机制 Event Loop 巨大的提升!重启的async函数和promises“译” 
async/await的基础用法 
Promise 初入门径 Promise 探讨 jQuery的deferred对象详解 Promises/A+ 规范 
相关代码 
–es6-promise