写在文本前:本文不讲概念,不谈基本思想,关于promise的基本知识可以自行百度查阅,这里主要是说一下关于promise我们在日常使用中忽略的或者需要理解的知识点。
1、什么是promise
我们在浏览器打印出Promise(console.dir(Promise)),看看Promise到底是什么,输出结果如下:
从打出来的结果可以看出,Promise是一个构造函数,自己身上有all、resolve、reject这几个眼熟的方法,原型上有then、catch、finally等方法。
2、创建Promise实例
要想创建一个promise对象、可以使用new来调用Promise的构造器来进行实例化。如下:
var promise = new Promise(function(resolve, reject) {
// 异步处理,处理结束后、调用resolve 或 reject
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
除了上面的方法我们还可以使用Promise.resolve 和 Promise.reject这两个方法创建实例,这两个静态方法Promise.resolve(value),Promise.reject(value) 可以认为是 new Promise() 方法的快捷方式。创建方式如下(以resolve为代表创建,reject同理):
new Promise(function(resolve){
resolve(100);
});
//使用情况
Promise.resolve(100).then(function(value){
console.log(value);
});
3、 Promise只能进行异步操作?
在使用Promise.resolve(value)等方法的时候,如果promise对象立刻就能进入resolve状态的话,那么你是不是觉得 .then
里面指定的方法就是同步调用的呢?
实际上,.then中指定的方法调用是异步进行的。看下边代码,先思考下打出来的信息顺序是什么?
var promise = new Promise(function (resolve){
console.log("inner promise"); // 1
resolve(42);
});
promise.then(function(value){
console.log(value); // 3
});
console.log("outer promise"); // 2
//打印出来的顺序是:
//inner promise
//outer promise
//42
由于JavaScript代码会按照文件的从上到下的顺序执行,所以最开始 <1> 会执行,然后是 resolve(42); 被执行。这时候 promise 对象的已经变为确定状态,FulFilled被设置为了 42 。照理说应该是打印出console.log(42)最后是console.log("outer promise");但是看结果却不是这样的,而是函数2比函数3先执行,到这里我想你也就明白了,即使在调用 promise.then 注册回调函数的时候promise对象已经是确定的状态,Promise也会以异步的方式调用该回调函数,这是在Promise设计上的规定方针。即:promise.then永远是以异步调用。
4、每次调用then都会返回一个新创建的promise对象
在使用过程中我想大家已经认识了 .then().catch() 这种链式方法的写法了,其实在Promise里可以将任意个方法连在一起作为一个方法链(method chain)。你可以无限的这样使用下去,比如promise.then().then().then().catch()这样,但是你有没有想过promise链式调用返回给下一步的数据是什么?
var p = new Promise(function(resolve,reject){
resolve("aaa")
})
var test = p.then(function(value){
console.log(value)
})
console.dir(test)
想一下上面的console.dir(test)打出来是什么?没错是一个promise对象,如下图
5、promise.then().then().then()....这样链式调用,后边的一个then()的值是谁传递的?
// 1: 对同一个promise对象同时调用 `then` 方法
var aPromise = new Promise(function (resolve) {
resolve(100);
});
aPromise.then(function (value) {
return value * 2;
});
aPromise.then(function (value) {
return value * 2;
});
aPromise.then(function (value) {
console.log("1: " + value); // => 100
})
// vs
// 2: 对 `then` 进行 promise chain 方式进行调用
var bPromise = new Promise(function (resolve) {
resolve(100);
});
bPromise.then(function (value) {
return value * 2;
}).then(function (value) {
return value * 2;
}).then(function (value) {
console.log("2: " + value); // => 100 * 2 * 2
});
//2个实例的输出值是
//1: 100
//2: 400
第1种写法中并没有使用promise的方法链方式,这在Promise中是应该极力避免的写法。这种写法中的 then 调用几乎是在同时开始执行的,而且传给每个 then 方法的 value 值都是 100 。
第2中写法则采用了方法链的方式将多个 then 方法调用串连在了一起,各函数也会严格按照 resolve → then → then → then 的顺序执行,并且传给每个 then 方法的 value 的值都是前一个promise对象通过 return 返回的值。