Javascript/ES6 Promise用法
Javascript Promise代表一个操作的结果还没有完成,将在未来某个时间有确定结果,比如网络请求操作,当我们从某个数据源抓取数据时,实际上没有办法绝对地知道什么时候能够接受到响应。
如果我们的一些操作依赖这个网络请求操作就会有问题,在没有Promise的情况下,我们得使用callback来处理响应完成时的动作,如果只有一个异步动作这也许没有问题,但是如果有多个异步动作,回调变得无法管理导致著名的回调陷阱。
doSomething(function(responseOne){doSomethingElse(responseOne,function(responseTwo,err){if(err){handleError(err);}doMoreStuff(responseTwo,function(responseThree,err){if(err){handleAnotherError(err);}doFinalThing(responseThree,function(err){if(err){handleAnotherError(err);}// Complete});// end doFinalThing});// end doMoreStuff});// end doSomethingElse});// end doSomething
Promise提供标准的干净的按照顺序发生的任务:
doSomething().then(doSomethingElse).catch(handleError).then(doMoreStuff).then(doFinalThing).catch(handleAnotherError)
创建Promise
一个Promise使用Promise构造器创建,这个函数接受两个参数resolve和reject:
varpromise=newPromise(function(resolve,reject){/* Promise content */})

在这个函数中,我们能够执行我们想要的异步任务,然后需要标记Promise状态,当标记promise为fulfilled时,我们需要调用resolve(),可选情况下可传递我们希望返回的一个值;如果失败,需要标记promise为rejected,调用reject();可选情况下可传递一个错误信息,在这个promise真正完成fulfilled或被拒绝rejected之前,它的状态是一个待定状态。
下面是XMLHttpRequest的promise版本:
functionget(url){returnnewPromise(function(resolve,reject){varreq=newXMLHttpRequest();req.open('GET',url);req.onload=function(){if(req.status==200){resolve(req.response);/* PROMISE RESOLVED */}else{reject(Error(req.statusText));/* PROMISE REJECTED */}};req.onerror=function(){reject(Error("Network Error"));};req.send();});}
使用Promise
一旦我们创建Promise,我们需要实际使用它,可以像普通函数调用,但是有些不同,需要访问其.then()方法。.then()方法接受两个可选参数,首先,如果promise被实现fulfilled第一个函数被调用,如果promise被拒绝第二个函数被调用:
get(url).then(function(response){/* successFunction */},function(err){/* errorFunction */})
处理错误
上面代码我们是将错误与成功放在同一个函数中,为了具有可读性,我们将成功和错误放在各种独立的两个.then()中。
get(url).then(function(response){/* successFunction */},undefined).then(undefined,function(err){/* errorFunction */})
为了了处理错误,我们可以使用.catch()方法,它是.then(undefined, errorFunction)的另外一种速记写法:
get(url).then(function(response){/* successFunction */}).catch(function(err){/* errorFunction */})
链式chaining
当有多个异步函数时我们需要按顺序执行,可以将多个.then()像链条一样串联起来,创建一个异步函数序列。
get(url).then(function(response){response=JSON.parse(response);varsecondURL=response.data.urlreturnget(secondURL);/* Return another Promise */}).then(function(response){response=JSON.parse(response);varthirdURL=response.data.urlreturnget(thirdURL);/* Return another Promise */}).catch(function(err){handleError(err);});
如果Promise链条中一个环节完成了,会按序列移动到下一个链条,如果有一个环节失败rejected,会直接跳到下一个错误函数.catch()。
并行执行Promise
如果能够并行执行这些链条上异步任务将会提高性能,现在我们需要两个方法来完成:Array.map()方法允许我们逐个执行数组中的动作,然后创建这些动作完成后的结果数组。
Promise.all()方法返回一个成功完成每个promise数组,如果任何这个数组中任何一个promise被拒绝也就是失败,Promise.all()会也拒绝或失败。
vararrayOfURLs=['one.json','two.json','three.json','four.json'];vararrayOfPromises=arrayOfURLs.map(get);Promise.all(arrayOfPromises).then(function(arrayOfResults){/* Do something when all Promises are resolved */}).catch(function(err){/* Handle error is any of Promises fails */})

通过开发工具我们会看到所有抓取请求是并行的:
