深入理解es6-Promise对象 (3)

参数是一个thenable对象
所谓的thenable对象指的就是具有then方法的对象,类似于类数组具有数组的length,但不是数组一样。
javascript let thenable = { then: function(resolve, reject) { resolve(42); } }; var promise = Promise.resolve(thenable) .then(value=>console.log(value));// 42
上面的例子就是将具有then方法的thenable对象转化为promise对象,并且立即执行resolve方法。

参数不是具有then方法的对象,或根本就不是对象
如果参数是一个原始值,或者是一个不具有then方法的对象,则Promise.resolve方法返回一个新的 Promise 对象,状态为resolved。
javascript var str = '17号' Promise.resolve(str).then(value=>console.log(value)) // 17号

Promise.reject()

返回一个新的 Promise 实例,该实例的状态为rejected。用法和resolve一样,但是都是以失败返回结果
Promise.reject() <=> new Promise((resolve,reject) = >reject())

ps:Promise.reject()方法的参数,会原封不动地作为reject的理由,变成后续方法的参数。这一点与Promise.resolve方法不一致。

const thenable = { then(resolve, reject) { reject('出错了'); } }; Promise.reject(thenable) .catch( e=> { console.log(e) }) // 返回的是thenable对象 Promise.all()

Promise.all 接收一个 promise对象的数组作为参数,当这个数组里的所有promise对象全部变为resolve或reject状态的时候,它才会去调用 .then() 方法。

该方法的参数是一个数组

该方法的参数数组是必须含有promise对象的数组

只有数组中所有的promise对象都变成resolve或者reject才能进行下一步操作。

// `delay`毫秒后执行resolve function timerPromisefy(delay) { return new Promise(function (resolve) { setTimeout(function () { resolve(delay); }, delay); }); } var startDate = Date.now(); // 所有promise变为resolve后程序退出 Promise.all([ timerPromisefy(1), timerPromisefy(32), timerPromisefy(64), timerPromisefy(128) ]).then(function (values) { console.log(Date.now() - startDate + 'ms'); console.log(values); }); // 129ms // 1,32,64,128

从上述结果可以看出,传递给 Promise.all 的promise并不是一个个的顺序执行的,而是同时开始、并行执行的。
假设法:如果这些promise全部串行处理的话,那么需要 等待1ms → 等待32ms → 等待64ms → 等待128ms ,全部执行完毕需要225ms的时间。但实际上不是,而是129ms左右。

Promise.race()

和Promise.all()方法一样,参数是一个数组,但是只要有一个promise对象更改状态时就实行下一步。

// `delay`毫秒后执行resolve function timerPromisefy(delay) { return new Promise(function (resolve) { setTimeout(function () { resolve(delay); }, delay); }); } // 任何一个promise变为resolve或reject 的话程序就停止运行 Promise.race([ timerPromisefy(1), timerPromisefy(32), timerPromisefy(64), timerPromisefy(128) ]).then(function (value) { console.log(value); // => 1 });

上面的例子是1秒后就resolve了,所以直接then()了。

Promsie.finally()

该方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。无论resolve还是reject都会实行的操作,不依赖其他的操作。按照执行顺序。

function promise(){ return new Promise((resolve, reject) => { resolve('success'); }) }; promise().then(data => { console.log(data) return Promise.reject('fail') }).finally(() => { console.log('end') }).catch(data =>{ console.log(data) }) // success // end // fail

从上面的例子可知,是按照promise的实行顺序执行的,在then()中,要求返回一个失败的状态,但是却没先实行失败的方法,而是按照顺序实行了finally方法。

Promise.done()

Promise 对象的回调链,不管以then方法或catch方法结尾,要是最后一个方法抛出错误,都有可能无法捕捉到(因为 Promise 内部的错误不会冒泡到全局)。因此,我们可以提供一个done方法,总是处于回调链的尾端,保证抛出任何可能出现的错误。

Promise.prototype.done = function (resolve, reject) { this.then(resolve, reject) .catch( function (reason) { // 抛出一个全局错误 setTimeout( () => { throw reason }, 0); }); } // 使用示例 var p = new Promise( (resolve, reject) => { resolve('p'); }); p.then(ret => { console.log(ret); return 'then1'; }).catch( err => { console.log(err.toString()); }).then( ret => { console.log(ret); return 'then2'; }).then( ret => { console.log(ret); x + 2; }).done();

该例子参考别人的例子。发现到最后直接抛出了 'Uncaught ReferenceError: x is not defined'。说明最后一个then实行时会抛出异常,也可以类似于catch方法吧。

总结

总结来说Promise其实就是做了一件事情,那就是对异步操作进行了封装,然后可以将异步操作以同步的流程表达出来,避免了层层嵌套的回调地狱,提供统一的接口方法,使得控制异步操作更加容易,但是也有一定的缺点,promise一旦没确定状态,是没法终止的,同样的,也无法取消promise。
如果本文有什么不对的地方,欢迎指出,谢谢,大家一起进步加油。我把笔记放到github了,如果满意的话给个star。

参考资料



学习Promise

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpjxdp.html