1.Promise的马上实行性varpnewPromise(function(resolve,reject){console.log(createapromise);resolve
1.Promise的马上实行性
var p = new Promise(function(resolve, reject){
console.log("create a promise");
resolve("success");
});
console.log("after new Promise");
p.then(function(value){
console.log(value);
});
掌握台输出:
"create a promise"
"after new Promise"
"success"
Promise对象示意将来某个将要发作的事宜,但在建立(new)Promise时,作为Promise参数传入的函数是会被马上实行的,只是个中实行的代码可所以异步代码。有些同学会以为,当Promise对象挪用then要领时,Promise吸收的函数才会实行,这是毛病的。因此,代码中”create a promise”先于”after new Promise”输出。
2.Promise 三种状况
var p1 = new Promise(function(resolve,reject){
resolve(1);
});
var p2 = new Promise(function(resolve,reject){
setTimeout(function(){
resolve(2);
}, 500);
});
var p3 = new Promise(function(resolve,reject){
setTimeout(function(){
reject(3);
}, 500);
});
console.log(p1);
console.log(p2);
console.log(p3);
setTimeout(function(){
console.log(p2);
}, 1000);
setTimeout(function(){
console.log(p3);
}, 1000);
p1.then(function(value){
console.log(value);
});
p2.then(function(value){
console.log(value);
});
p3.catch(function(err){
console.log(err);
});
掌握台输出:
Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: 1}
Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
1
2
3
Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: 2}
Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: 3}
Promise的内部实现是一个状况机。Promise有三种状况:pending,resolved,rejected。当Promise刚建立完成时,处于pending状况;当Promise中的函数参数实行了resolve后,Promise由pending状况变成resolved状况;如果在Promise的函数参数中实行的不是resolve要领,而是reject要领,那末Promise会由pending状况变成rejected状况。
p2、p3刚建立完成时,掌握台输出的这两台Promise都处于pending状况,但为何p1是resolved状况呢? 这是由于p1 的函数参数中实行的是一段同步代码,Promise刚建立完成,resolve要领就已被挪用了,因此紧跟着的输出显现p1是resolved状况。我们经由历程两个setTimeout
函数,耽误1s后再次输出p2、p3的状况,此时p2、p3已实行完成,状况离别变成resolved和rejected。
3.Promise 状况的不可逆性
var p1 = new Promise(function(resolve, reject){
resolve("success1");
resolve("success2");
});
var p2 = new Promise(function(resolve, reject){
resolve("success");
reject("reject");
});
p1.then(function(value){
console.log(value);
});
p2.then(function(value){
console.log(value);
});
掌握台输出:
"success1"
"success"
Promise状况的一旦变成resolved或rejected时,Promise的状况和值就牢固下来了,不管你后续再怎样挪用resolve或reject要领,都不能转变它的状况和值。因此,p1中resolve("success2")
并不能将p1的值更改成success2
,p2中reject("reject")
也不能将p2的状况由resolved转变成rejected.
4.链式挪用
var p = new Promise(function(resolve, reject){
resolve(1);
});
p.then(function(value){ //第一个then
console.log(value);
return value*2;
}).then(function(value){ //第二个then
console.log(value);
}).then(function(value){ //第三个then
console.log(value);
return Promise.resolve('resolve');
}).then(function(value){ //第四个then
console.log(value);
return Promise.reject('reject');
}).then(function(value){ //第五个then
console.log('resolve: '+ value);
}, function(err){
console.log('reject: ' + err);
})
掌握台输出:
1
2
undefined
"resolve"
"reject: reject"
Promise对象的then要领返回一个新的Promise对象,因此能够经由历程链式挪用then要领。then要领吸收两个函数作为参数,第一个参数是Promise实行胜利时的回调,第二个参数是Promise实行失利时的回调。两个函数只会有一个被挪用,函数的返回值将被用作建立then返回的Promise对象。这两个参数的返回值可所以以下三种状况中的一种:
-
return
一个同步的值 ,或许 undefined
(当没有返回一个有效值时,默许返回undefined),then
要领将返回一个resolved状况的Promise对象,Promise对象的值就是这个返回值。 -
return
另一个 Promise,then
要领将依据这个Promise的状况和值建立一个新的Promise对象返回。 -
throw
一个同步非常,then
要领将返回一个rejected状况的Promise, 值是该非常。
依据以上剖析,代码中第一个then
会返回一个值为2(1*2),状况为resolved的Promise对象,因而第二个then
输出的值是2。第二个then
中没有返回值,因此将返回默许的undefined,因而在第三个then
中输出undefined。第三个then
和第四个then
中离别返回一个状况是resolved的Promise和一个状况是rejected的Promise,顺次由第四个then
中胜利的回调函数和第五个then
中失利的回调函数处置惩罚。
5.Promise then() 回调异步性
var p = new Promise(function(resolve, reject){
resolve("success");
});
p.then(function(value){
console.log(value);
});
console.log("which one is called first ?");
掌握台输出:
"which one is called first ?"
"success"
Promise吸收的函数参数是同步实行的,但then
要领中的回调函数实行则是异步的,因此,”success”会在背面输出。
6.Promise 中的非常
var p1 = new Promise( function(resolve,reject){
foo.bar();
resolve( 1 );
});
p1.then(
function(value){
console.log('p1 then value: ' + value);
},
function(err){
console.log('p1 then err: ' + err);
}
).then(
function(value){
console.log('p1 then then value: '+value);
},
function(err){
console.log('p1 then then err: ' + err);
}
);
var p2 = new Promise(function(resolve,reject){
resolve( 2 );
});
p2.then(
function(value){
console.log('p2 then value: ' + value);
foo.bar();
},
function(err){
console.log('p2 then err: ' + err);
}
).then(
function(value){
console.log('p2 then then value: ' + value);
},
function(err){
console.log('p2 then then err: ' + err);
return 1;
}
).then(
function(value){
console.log('p2 then then then value: ' + value);
},
function(err){
console.log('p2 then then then err: ' + err);
}
);
掌握台输出:
p1 then err: ReferenceError: foo is not defined
p2 then value: 2
p1 then then value: undefined
p2 then then err: ReferenceError: foo is not defined
p2 then then then value: 1
Promise中的非常由then
参数中第二个回调函数(Promise实行失利的回调)处置惩罚,非常信息将作为Promise的值。非常一旦获得处置惩罚,then
返回的后续Promise对象将恢复一般,并会被Promise实行胜利的回调函数处置惩罚。别的,须要注重p1、p2 多级then
的回调函数是交替实行的 ,这正是由Promise then
回调的异步性决议的。
7.Promise.resolve()
var p1 = Promise.resolve( 1 );
var p2 = Promise.resolve( p1 );
var p3 = new Promise(function(resolve, reject){
resolve(1);
});
var p4 = new Promise(function(resolve, reject){
resolve(p1);
});
console.log(p1 === p2);
console.log(p1 === p3);
console.log(p1 === p4);
console.log(p3 === p4);
p4.then(function(value){
console.log('p4=' + value);
});
p2.then(function(value){
console.log('p2=' + value);
})
p1.then(function(value){
console.log('p1=' + value);
})
掌握台输出:
true
false
false
false
p2=1
p1=1
p4=1
Promise.resolve(...)
能够吸收一个值或许是一个Promise对象作为参数。当参数是一般值时,它返回一个resolved状况的Promise对象,对象的值就是这个参数;当参数是一个Promise对象时,它直接返回这个Promise参数。因此,p1 === p2。但经由历程new的体式格局建立的Promise对象都是一个新的对象,因此背面的三个比较效果都是false。别的,为何p4的then
最早挪用,但在掌握台上是末了输出效果的呢?由于p4的resolve
中吸收的参数是一个Promise对象p1,resolve
会对p1”拆箱“,猎取p1的状况和值,但这个历程是异步的,可参考下一节。
8.resolve vs reject
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'));
});
p1.then(
function fulfilled(value){
console.log('fulfilled: ' + value);
},
function rejected(err){
console.log('rejected: ' + err);
}
);
p2.then(
function fulfilled(value){
console.log('fulfilled: ' + value);
},
function rejected(err){
console.log('rejected: ' + err);
}
);
p3.then(
function fulfilled(value){
console.log('fulfilled: ' + value);
},
function rejected(err){
console.log('rejected: ' + err);
}
);
掌握台输出:
p3 rejected: [object Promise]
p1 fulfilled: resolve
p2 rejected: reject
Promise回调函数中的第一个参数resolve
,会对Promise实行”拆箱”行动。即当resolve
的参数是一个Promise对象时,resolve
会”拆箱”猎取这个Promise对象的状况和值,但这个历程是异步的。p1″拆箱”后,猎取到Promise对象的状况是resolved,因此fulfilled
回调被实行;p2″拆箱”后,猎取到Promise对象的状况是rejected,因此rejected
回调被实行。但Promise回调函数中的第二个参数reject
不具备”拆箱“的才能,reject的参数会直接传递给then
要领中的rejected
回调。因此,纵然p3 reject
吸收了一个resolved状况的Promise,then
要领中被挪用的依然是rejected
,而且参数就是reject
吸收到的Promise对象。
迎接关注我的民众号:老干部的大前端,领取21本大前端精选书本!