在 掘金上瞥见一篇写promise的文章,觉得作者写的很棒,文章链接在这:八段代码完全控制 Promise 。看完以后觉得学到了许多,所以又从新把JavaScript Promise迷你书(中文版)刷了一遍,以下是我关于promise的明白。
Promise 是什么?
所谓Promise,简朴说就是一个容器,内里保存着某个将来才会完毕的事宜(通常是一个异步操纵)的效果。从语法上说,Promise 是一个对象,从它能够猎取异步操纵的音讯。Promise 供应一致的 API,种种异步操纵都能够用一样的要领举行处置惩罚。 —— ECMAScript 6 入门 阮一峰
Promise对象代表一个异步操纵,有三种状况:Pending(预备状况),Fulfilled(胜利状况,也称为Resolved状况),Rejected(失利状况)。只要异步操纵的效果能够决议promise对象的状况,操纵胜利后,promise对象由Pending状况转换为Fulfilled状况,此时回调函数会实行 onFulfilled要领。反之,操纵失利,promise对象由pending状况转换为Rejected状况,此时回调函数会实行onRejected要领。
以下图所示:
建立一个Promise对象
var p1 = new Promise(function(resolve,reject){
resolve('resolve');
});
var p2 = new Promise(function(resolve,reject){
reject('reject');
});
p1 返回一个resolved状况,值为resolve的Promise对象
Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: "resolve"}
p2 返回一个rejected状况,值为reject的Promise对象
Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: "reject"}
Promise 的基础API
1.Promise#then
Promise.then(onFulfilled,onRejected)
then要领定义了promise状况变成resolved或许rejected状况以后的回调函数:
- pending->resolved:实行onFulfilled函数,而且将promise对象的值传给onFulfilled函数
- pending->rejected:实行onRejected函数,而且将promise对象的值传给onRejected函数
代码示例以下:
var p = new Promise(function(resolve, reject){
console.log("create a promise");
resolve("success");
});
console.log("after new Promise");
p.then(function onFulfilled(value){
console.log(value);
},function onRejected(error){
console.log(error);
});
运转效果以下:
"create a promise"
"after new Promise"
"success"
new Promise返回一个resolved状况的promise对象,所以在p.then()要领中挪用的是onFulfilled函数。
建立promise时,promise对象中的函数是马上实行的,并非在挪用then要领的时刻才会去实行,所以首先会输出”create a promise”。然则实行的代码是异步代码,所以”after new Promise”会在”success”之前输出。
2.Promise#catch
promise.catch(onRejected);
catch要领捕捉了promise运转过程当中的非常。catch与then要领中的onRejected的差异是,onRejected 函数只能在promise状况变成rejected的时刻挪用,但catch既能够在promise状况变成rejected的时刻挪用,又能够捕捉第一个onFulfilled要领中涌现的毛病。
能够参考promise迷你书中的这一段代码:
function throwError(value) {
// 抛出非常
throw new Error(value);
}
// <1> onRejected不会被挪用
function badMain(onRejected) {
return Promise.resolve(42).then(throwError, onRejected);
}
// <2> 有非常发作时onRejected会被挪用
function goodMain(onRejected) {
return Promise.resolve(42).then(throwError).catch(onRejected);
}
// 运转示例
badMain(function(){
console.log("BAD");
});
goodMain(function(){
console.log("GOOD");
});
在这段代码中,badMain函数中传入onRejected参数,由于Promise.resolve(42)返回一个resolved状况的promise对象(这个api的用法会在下一节中说到),所以会去挪用throwError函数,throwError函数中抛出的非常onRejected是捕捉不到的,然则catch能够捕捉到。
3.Promise.resolve
这个要领会根据传进来的参数的差异,返回差异的promise对象。
//1.传入的参数是一个一般值
var p1 = Promise.resolve(1);//返回一个将该对象作为值的新promise对象
//2.传入的参数是一个Promise对象
var p2 = Promise.resolve(p1);//返回吸收到的promise对象
p1 === p2 //true
在迷你书中引见了三种状况,除了上面两种以外,另有一种thenable范例的对象的时刻,那种这里就不做引见了,有兴致的朋侪能够本身去看看啊~
4.Promise.reject
这个要领跟Promise.resolve要领一样,会根据传进来的参数的差异,返回差异的promise对象。
//1.传入的参数是一个一般值
var p3 = Promise.reject(1);//返回一个将该对象作为值的新promise对象
//2.传入的参数是一个Promise对象
var p4 = Promise.reject(p3);//返回一个新的promise对象
p3 === p4 //false
跟resolve差异的是,当传入的参数是一个Promise对象的时刻,会返回一个rejected状况的新promise对象。
5.Promise.all
Promise.all吸收一个 promise对象的数组作为参数,当这个数组里的一切promise对象悉数变成resolve或reject状况的时刻,它才会去挪用 .then 要领。
示例代码:
var p1 = Promise.resolve(1),
p2 = Promise.resolve(2),
p3 = Promise.resolve(3);
Promise.all([p1, p2, p3]).then(function (results) {
console.log(results); // [1, 2, 3]
});
6.Promise.race
Promise.race也是吸收一个 promise对象的数组作为参数,参数 promise 数组中的任何一个promise对象假如变成resolve或许reject的话, 该函数就会返回,并运用这个promise对象的值举行resolve或许reject。
var p1 = Promise.resolve(1),
p2 = Promise.resolve(2),
p3 = Promise.resolve(3);
Promise.race([p1, p2, p3]).then(function (value) {
console.log(value); // 1
});
这里须要注重的是,虽然在p1resolved以后便实行了then要领,然则并非意味着今后的promise对象不实行了,其他的照样promise对象照样要实行的,只是不会再挪用then函数。
下面这个demo便能够看出:
var p1 = new Promise(function(resolve,reject){
console.log('I am p1!');
resolve(1);
});
var p2 = new Promise(function(resolve,reject){
console.log('I am p2!');
resolve(2);
});
var p3 = new Promise(function(resolve,reject){
console.log('I am p3!');
resolve(3);
});
Promise.race([p1, p2, p3]).then(function (value) {
console.log(value);
});
运转效果:
I am p1!
I am p2!
I am p3!
1
Promise Demo
这是个很大的demo,,^-^, 涵盖了许多小知识点,
var p_1 = new Promise(function(resolve,reject){
resolve(1);
});
var p_2 = Promise.resolve(1);
var p_3 = Promise.reject(1);
var p_4 = Promise.resolve(p_2);
// 体式格局1
var p1 = new Promise(function(resolve, reject){
resolve(Promise.resolve('resolve'));
});
var p2 = new Promise(function(resolve, reject){
resolve(Promise.reject('reject'));
});
var p3 = new Promise(function(resolve, reject){
reject(Promise.resolve('resolve'));
});
var p4 = new Promise(function(resolve, reject){
reject(Promise.reject('reject'));
});
//体式格局2
var p1 = Promise.resolve(Promise.resolve('resolve'))
var p2 = Promise.resolve(Promise.reject('reject'))
var p3 = Promise.reject(Promise.resolve('resolve'))
var p4 = Promise.reject(Promise.reject('reject'))
//定义回调函数
p1.then(
function fulfilled(value){
console.log('fulfilled1: ' + value);
},
function rejected(err){
console.log('rejected1: ' + err);
}
);
p2.then(
function fulfilled(value){
console.log('fulfilled2: ' + value);
},
function rejected(err){
console.log('rejected2: ' + err);
}
);
p3.then(
function fulfilled(value){
console.log('fulfilled3: ' + value);
},
function rejected(err){
console.log('rejected3: ' + err);
}
);
p4.then(
function fulfilled(value){
console.log('fulfilled4: ' + value);
},
function rejected(err){
console.log('rejected4: ' + err);
}
);
采纳new Promise 体式格局建立对象和采纳Promise.resolve要领建立出来的对象实际上是一样的,能够把Promise.resolve看作new Promise 的语法糖。只不过须要注重的是,在上面引见resolve要领的时刻说过,假如传入的参数是一个promise对象,会直接返回这个对象,,所以p_2===p_4
输出的是true,然则经由过程new的体式格局建立出来的对象都是新建立的,所以new出来的对象跟别的对象都不会全等,即p_1===p_2
会输出false。
两种体式格局定义的p1,p2,p3,p4都是雷同的,从这段代码能够看出,不论是用那种体式格局建立promise对象,假如运用Promise.resolve要领传入一个新对象,照样会去‘读取’(可明白为)这个对象的,然则Promise.reject要领传入一个新对象,并不会去‘读取’这个对象,而会直接返回这个这个对象。(这个‘读取’的观点并非promise中的观点,只是我的个人明白,在八段代码完全控制 Promise 这篇文章中,作者把他解释为‘拆箱’,也是作者的一种让人明白起来更简朴的思绪,至于promise官方文档中的划定,现在还没有去细致深入研讨,有时间会去看一下^-^)
从这段代码能够看出,两种体式格局的实行递次会有差异,至于为何,本日也查找了许多材料,然则并没有找到缘由,有研讨过的大神迎接指点~~