nodejs13
2017-10-30 本文已影响0人
我_巨可爱
promise 总结
promise是异步编程的解决方案,用社区提供,标准化到ES6中。该对象中存储着某个时间才会结束的事件。
- 三中状态
- pending
- resolved
- rejected
- 状态一旦改变,不能再改变
- 缺点
- pending时,无法知道进行到哪一种状态
- 不可取消
- 必须有回调函数
- 如果该事件经常发生,stream模式更好
延时参数传参
- setInterval("funName('aa')",1000); aa加单引号是字符串,不加是变量
- var timeoutID = window.setTimeout(func[, delay, param1, param2, ...]);
- 需要注意的是,IE9 及更早的 IE 浏览器不支持第二种语法中向延迟函数传递额外参数的功能。
基本用法
var promise = new Pormise(function(resolve,reject){
if ("异步成功") {
resolve(value);// 改变状态,哪怕多次调用,也只会执行一次
}else {
reject(err);
}
});
// 使用then指定resolve和reject 的回调函数
promise.then(function(value){
},function(err){
})
- Promise是对象,它的实例需要创建
- 切换promise对象
- p1的resolve方法调用时,参数是另一个promise实例
Promise.prototype.then可以链式编程
- then会返回一个新的promise 对象,不是原来的那一个。
- 第一个then完成以后,会将返回结果作为参数,传入第二个then
- 如果第一个then行完毕,返回值是非promise实例,会调用第二个then的第一个函数,参数就是第一个then的返回值。
- 如果第一个回调函数执行完毕,返回值是promise 实例,第二个回调函数会等到自己的状态改变再执行。
Promise.prototype.catch
- 当一个promise实例的then既有第二个回调函数,又有catch时。当promise的状态改为reject只会执行then的第二个回调函数
- catch可以捕获的错误有
- 创建promise实例时,将状态改为reject
- 创建promise实例时的有错误,但是要在状态改为resolve之前
- 调用resolve的回调函数,但是回调函数出错
- 没有使用catch方法,实例状态也没有改变时,创建实例对象中的错误不会传递到外层,即不会有任何反应。但是chrome浏览器会抛出错误。
- Node 有一个unhandledRejection事件,专门监听未捕获的reject错误。
//本来不会报错
var someAsyncThing = function() {
return new Promise(function(resolve, reject) {
// 下面一行会报错,因为x没有声明
resolve(x + 2);
});
};
someAsyncThing().then(function() {
console.log('everything is great');
});
//替catch行道
process.on('unhandledRejection', function (err, p) {
console.error(err.stack)
});
- catch方法也可以返回一个promise对象,继续调用then。如果catch没执行,跳过catch继续执行then
promise.all
将多个promise实例包裹成一个promise实例,当所有的promise实例都变成fulfilled,或者有一个promise实例变成reject,就会触发后续函数。
promise.race
在一定时间内,被包裹的promise实例们,有一个改变就传出该promise实例。该promise实例继续调用then或者catch方法。在一定时间内没有改变,就默认为rejected状态。
promise.resolve
这是一个常用的方法,可以将很多的东西转化成promise对象。
注意:立即resolve的Promise对象,是在本轮“事件循环”(event loop)的结束时,而不是在下一轮“事件循环”的开始时。
- 参数是promise对象,使用该方法,原样返回
- 参数是对象并有then方法,将该对象改成promise对象,状态为resolved,立即执行then方法
- 参数是对象但是没有then方法,或者不是对象。依旧返回该promise,立即执行then,参数就是该对象或者非对象数据
- 无参数,返回promise对象,立即调用then方法。
var jsPromise = Promise.resolve($.ajax('/whatever.json'));
//上面代码将jQuery生成的deferred对象,转为一个新的Promise对象。t
promise.reject
该方法也会返回一个新的 Promise 实例,该实例的状态为rejected。
- 注意,
Promise.reject()
方法的参数,会原封不动地作为reject的理由,变成后续方法的参数。这一点与Promise.resolve方法不一致。
超级有用的方法
使用catch结尾也不能捕获所有的错误,可以使用done来解决。下面两个方法需要自己部署
Promise.prototype.done = function (onFulfilled, onRejected) {
this.then(onFulfilled, onRejected)
.catch(function (reason) {
// 抛出一个全局错误
setTimeout(() => { throw reason }, 0);
});
};
好处:
- promise没有catch方法时,该方法的第二个函数可捕获
- promise的catch中再抛出错误,也会冒泡到全局
- promise中有catch并触发,会调用done的第一函数,代表前边都自己搞定,不需要done了
finally方法用于指定不管Promise对象最后状态如何,都会执行的操作。它与done方法的最大区别,它接受一个普通的回调函数作为参数,该函数不管怎样都必须执行。
Promise.prototype.finally = function (callback) {
let P = this.constructor;
return this.then(
value => P.resolve(callback()).then(() => value),
reason => P.resolve(callback()).then(() => { throw reason })
);
};