热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

八段代码完全控制Promise

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本大前端精选书本!

《八段代码完全控制Promise》


推荐阅读
author-avatar
昙檀禅潺_162
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有