
Promise是一个构造函数,本身身上有all、reject、resolve这几个眼熟的方法,原型上有then、catch等一样很眼熟的方法。数组
var p = new Promise(function(resolve, reject){ //作一些异步操做 setTimeout(function(){ console.log('执行完成'); resolve('随便什么数据'); }, 2000); });
Promise的构造函数接收一个参数,是函数,而且传入两个参数:resolve,reject,分别表示异步操做执行成功后的回调函数和异步操做执行失败后的回调函数。其实这里用“成功”和“失败”来描述并不许确,按照标准来说,resolve是将Promise的状态置为fullfiled,reject是将Promise的状态置为rejected。不过在咱们开始阶段能够先这么理解,后面再细究概念。dom
function runAsync(){ var p = new Promise(function(resolve, reject){ //作一些异步操做 setTimeout(function(){ console.log('执行完成'); resolve('随便什么数据'); }, 2000); }); return p; } runAsync()
runAsync().then(function(data){ console.log(data); //后面能够用传过来的数据作些其余操做 //...... });
function runAsync(callback){ setTimeout(function(){ console.log('执行完成'); callback('随便什么数据'); }, 2000); } runAsync(function(data){ console.log(data); });
效果也是同样的,还费劲用Promise干吗。那么问题来了,有多层回调该怎么办?若是callback也是一个异步操做,并且执行完后也须要有相应的回调函数,该怎么办呢?总不能再定义一个callback2,而后给callback传进去吧。而Promise的优点在于,能够在then方法中继续写Promise对象并返回,而后继续调用then来进行回调操做。异步
runAsync1() .then(function(data){ console.log(data); return runAsync2(); }) .then(function(data){ console.log(data); return runAsync3(); }) .then(function(data){ console.log(data); });
这样可以按顺序,每隔两秒输出每一个异步回调中的内容,在runAsync2中传给resolve的数据,能在接下来的then方法中拿到。运行结果以下:函数
猜猜runAsync一、runAsync二、runAsync3这三个函数都是如何定义的?没错,就是下面这样post
function runAsync1(){ var p = new Promise(function(resolve, reject){ //作一些异步操做 setTimeout(function(){ console.log('异步任务1执行完成'); resolve('随便什么数据1'); }, 1000); }); return p; } function runAsync2(){ var p = new Promise(function(resolve, reject){ //作一些异步操做 setTimeout(function(){ console.log('异步任务2执行完成'); resolve('随便什么数据2'); }, 2000); }); return p; } function runAsync3(){ var p = new Promise(function(resolve, reject){ //作一些异步操做 setTimeout(function(){ console.log('异步任务3执行完成'); resolve('随便什么数据3'); }, 2000); }); return p; }
在then方法中,你也能够直接return数据而不是Promise对象,在后面的then中就能够接收到数据了,好比咱们把上面的代码修改为这样:spa
runAsync1() .then(function(data){ console.log(data); return runAsync2(); }) .then(function(data){ console.log(data); return '直接返回数据'; //这里直接返回数据 }) .then(function(data){ console.log(data); });
那么输出就变成了这样:3d
function getNumber(){ var p = new Promise(function(resolve, reject){ //作一些异步操做 setTimeout(function(){ var num = Math.ceil(Math.random()*10); //生成1-10的随机数 if(num<=5){ resolve(num); } else{ reject('数字太大了'); } }, 2000); }); return p; } getNumber() .then( function(data){ console.log('resolved'); console.log(data); }, function(reason, data){ console.log('rejected'); console.log(reason); } );
getNumber() .then(function(data){ console.log('resolved'); console.log(data); }) .catch(function(reason){ console.log('rejected'); console.log(reason); });
效果和写在then的第二个参数里面同样。不过它还有另一个做用:在执行resolve的回调(也就是上面then中的第一个参数)时,若是抛出异常了(代码出错了),那么并不会报错卡死js,而是会进到这个catch方法中。请看下面的代码:code
getNumber() .then(function(data){ console.log('resolved'); console.log(data); console.log(somedata); //此处的somedata未定义 }) .catch(function(reason){ console.log('rejected'); console.log(reason); });
Promise .all([runAsync1(), runAsync2(), runAsync3()]) .then(function(results){ console.log(results); });
Promise .race([runAsync1(), runAsync2(), runAsync3()]) .then(function(results){ console.log(results); });
//请求某个图片资源 function requestImg(){ var p = new Promise(function(resolve, reject){ var img = new Image(); img.onload = function(){ resolve(img); } img.src = 'xxxxxx'; }); return p; } //延时函数,用于给请求计时 function timeout(){ var p = new Promise(function(resolve, reject){ setTimeout(function(){ reject('图片请求超时'); }, 5000); }); return p; } Promise .race([requestImg(), timeout()]) .then(function(results){ console.log(results); }) .catch(function(reason){ console.log(reason); });