Promise 对象用于表示一个异步操作的最终完成 (或失败), 及其结果值。推荐文档

简单使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const promise1 = new Promise((resolve, reject) => {
// resolve,异步操作完成结果,指引本函数执行 then 中的代码
// reject,异步操作失败结果,指引本函数执行 catch 中的代码
// *** resolve 或 reject 任何一个执行,即代表本函数逻辑执行完成,不再执行本函数的其它代码
resolve('It is value.')
setTimeout(() => {
reject('It is err.')
}, 3000);
});

promise1.then((value) => {
console.log(value);
// 输出(resolve 执行,reject 不执行): "It is value."
}).catch((err) => {
console.log(err);
// 输出(reject 执行,resolve 不执行): "It is err."
});

console.log(promise1);
// 输出: [object Promise]

参数

executor [ɪɡˈzekjətər],执行器,是 Promise 的唯一参数。

executor 是一个函数,这个函数包含两个参数,分别为 resolve 和 reject。
resolve 代表 Promise 执行完成,Promise 状态变为 fulfilled,并执行 then 回调返回执行结果;
reject 代表 Promise 执行失败,Promise 状态变为 rejected,并执行 catch 回调抛出错误信息;

状态

Promise 有 3 种状态,分别为 pending、fulfilled 和 rejected。

pending

初始状态,既不是成功,也不是失败状态。

fulfilled

意味着操作成功完成;

rejected

意味着操作失败。

注意:如果一个 promise 对象处在 fulfilled 或 rejected 状态而不是 pending 状态,那么它也可以被称为 settled 状态。你可能也会听到一个术语 resolved ,它表示 promise 对象处于 settled 状态。

链式调用

因为 Promise.prototype.then 和 Promise.prototype.catch 方法返回promise 对象, 所以它们可以被链式调用。

Promise 链式调用

属性

  • Promise.length:其值总是为 1 (构造器参数的数目);
  • Promise.prototype:表示 Promise 构造器的原型。

方法

Promise.all(iterable)

Promise.all(iterable) 方法返回一个 Promise 实例,此实例在 iterable(一个可迭代对象,Array 或 String) 参数内所有的 promise 都“完成(resolved)”或参数中不包含 promise 时回调完成(resolve);如果参数中 promise 有一个失败(rejected),此实例回调失败(reject),失败的原因是第一个失败 promise 的结果。

1
2
3
4
5
6
7
8
9
10
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 2000, 'foo');
});

Promise.all([promise1, promise2, promise3]).then((values) => {
console.log(values);
});
// 2s 后输出: Array [3, 42, "foo"]

返回值

  • resolved
    • 参数为空的可迭代对象,返回一个已完成(already resolved)状态的 Promise;
    • 参数不包含任何 promise,返回一个异步完成(asynchronously resolved) Promise。
  • rejected
    • 无参数,返回一个 rejected 状态的 Promise,并报错Uncaught (in promise) TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined
    • 参数中存在 rejected,返回一个 rejected 状态的 Promise,并报错指出在参数中 rejected 的位置。
  • 其他情况返回一个处理中(pending)的Promise。

Promise.race(iterable)

Promise.race(iterable) 方法返回一个 promise,一旦迭代器中的某个 promise 解决 或 拒绝,返回的 promise 就会 解决 或 拒绝。

1
2
3
4
5
6
7
8
9
10
11
12
const promise1 = new Promise((resolve, reject) => {
setTimeout(resolve, 3000, 'one');
});

const promise2 = new Promise((resolve, reject) => {
setTimeout(resolve, 1000, 'two');
});

Promise.race([promise1, promise2]).then((value) => {
console.log(value);
});
// 1s 后输出: "two"

Promise.reject(reason)

Promise.reject(reason) 方法返回一个带有拒绝原因的Promise对象。

1
2
3
4
5
6
7
8
9
10
function resolved(result) {
console.log('Resolved');
}

function rejected(result) {
console.error(result);
}

Promise.reject(new Error('fail')).then(resolved, rejected);
// 输出: Error: fail

Promise.resolve(value)

Promise.resolve(value)方法返回一个以给定值解析后的Promise 对象。如果这个值是一个 promise ,那么将返回这个 promise ;如果这个值是thenable(即带有”then” 方法),返回的promise会“跟随”这个thenable的对象,采用它的最终状态;否则返回的promise将以此值完成。此函数将类promise对象的多层嵌套展平。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// Resolve一个thenable对象
var p1 = Promise.resolve({
then: function(onFulfill, onReject) { onFulfill("fulfilled!"); }
});
console.log(p1 instanceof Promise) // true, 这是一个Promise对象

p1.then(function(v) {
console.log(v); // 输出"fulfilled!"
}, function(e) {
// 不会被调用
});

// Thenable在callback之前抛出异常
// Promise rejects
var thenable = { then: function(resolve) {
throw new TypeError("Throwing");
resolve("Resolving");
}};

var p2 = Promise.resolve(thenable);
p2.then(function(v) {
// 不会被调用
}, function(e) {
console.log(e); // TypeError: Throwing
});

// Thenable在callback之后抛出异常
// Promise resolves
var thenable = { then: function(resolve) {
resolve("Resolving");
throw new TypeError("Throwing");
}};

var p3 = Promise.resolve(thenable);
p3.then(function(v) {
console.log(v); // 输出"Resolving"
}, function(e) {
// 不会被调用
});

原型

Promise.prototype.constructor(),返回被创建的实例函数. 默认为 Promise 函数。

Promise.prototype.catch(onRejected)

catch() 方法返回一个Promise,并且处理拒绝的情况。它的行为与调用 Promise.prototype.then(undefined, onRejected) 相同。

无法捕获错误示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//创建一个新的 Promise ,且已决议
var p1 = Promise.resolve("calling next");

var p2 = p1.catch(function (reason) {
//这个方法永远不会调用
console.log("catch p1!");
console.log(reason);
});

p2.then(function (value) {
console.log("next promise's onFulfilled"); /* next promise's onFulfilled */
console.log(value); /* calling next */
}, function (reason) {
console.log("next promise's onRejected");
console.log(reason);
});

// 在异步函数中抛出的错误不会被catch捕获到
var p3 = new Promise(function(resolve, reject) {
setTimeout(function() {
throw 'Uncaught Exception!';
}, 1000);
});

p3.catch(function(e) {
console.log(e); // 不会执行
});

// 在resolve()后面抛出的错误会被忽略
var p4 = new Promise(function(resolve, reject) {
resolve();
throw 'Silenced Exception!';
});

p4.catch(function(e) {
console.log(e); // 不会执行
});

Promise.prototype.then(onFulfilled, onRejected)

then() 方法返回一个 Promise。它最多需要有两个参数:Promise 的成功和失败情况的回调函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const promise1 = new Promise((resolve, reject) => {
//resolve('Success!');
reject('Filled!')
});

promise1.then((value) => {
console.log(value);
// resolve 先执行则输出: "Success!"
},(err)=>{
console.log(err)
// reject 先执行则输出: "Filled!"
})

// *********** 与上方等同 ************
promise1.then((value) => {
console.log(value);
// resolve 先执行则输出: "Success!"
}).catch((err)=>{
console.log(err)
// reject 先执行则输出: "Filled!"
})

Promise.prototype.finally(onFinally)

finally() 方法返回一个Promise。在promise结束时,无论结果是fulfilled或者是rejected,都会执行指定的回调函数。
这避免了同样的语句需要在then()和catch()中各写一次的情况(例如,发一次请求,无论请求成功与否,都需要记录一次请求总次数)。

示例

1
2
3
4
5
Promise.resolve(2).then(() => {}, () => {}) // resolve 的结果为 undefined
Promise.resolve(2).finally(() => {}) // resolve 的结果为 2

Promise.reject(3).then(() => {}, () => {}) // resolve 的结果为 undefined
Promise.reject(3).finally(() => {}) // rejected 的结果为 3

实例

该实例为使用 XHR 加载图像。
源码及步骤详解
演示地址

手写 Promise

通过手写 Promise 来深刻理解 Promise。

参数及状态设计

  • 参数:executor,详细请看 参数
  • 状态:pending、fulfilled(resolved)和 rejected,详细请看 状态

设计代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class MyPromise {
constructor(executor) {
// 默认为 pending (等待)状态
this.PromiseStatus = 'pending';
// 默认为值为 undefined
this.PromiseValue = undefined;
// executor 中的 resolve 方法
let resolve = value => {
if(this.PromiseStatus === 'pending'){
// 将 MyPromise 状态更改为 resolved
this.PromiseStatus = 'resolved';
}
// 更新 MyPromise 的 value
this.PromiseValue = value;
}
// executor 中的 reject 方法
let reject = reason => {
if(this.PromiseStatus === 'pending'){
// 将 MyPromise 状态更改为 rejected
this.PromiseStatus = 'rejected'
}
// 更新 MyPromise 的 value
this.PromiseValue = reason;
// 抛出错误信息
console.error(reason);
}
// 捕获,若 executor 报错,直接执行 reject
try{
executor(resolve, reject)
}catch(err) {
reject(err)
}
}
}

测试代码

1
2
3
4
5
6
7
8
9
10
11
var p1 = new Promise(() => {})
var p2 = new Promise((resolve, reject) => {resolve(123)})
var p3 = new Promise((resolve, reject) => {reject(123)})

var mp1 = new MyPromise(() => {})
var mp2 = new MyPromise((resolve, reject) => {resolve(123)})
var mp3 = new MyPromise((resolve, reject) => {reject(123)})

console.log(p1,mp1)
console.log(p2,mp2)
console.log(p3,mp3)

测试截图

复制代码到控制台试试吧~

手写 Promise 1

then 方法设计

then() 方法有两个参数,onFulfilled 和 onRejected,详细请看 Promise.prototype.then

设计代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class MyPromise {
constructor(executor) {
// 默认为 pending (等待)状态
this.PromiseStatus = 'pending';
// 默认为值为 undefined
this.PromiseValue = undefined;
// executor 中的 resolve 方法
let resolve = value => {
if(this.PromiseStatus === 'pending'){
// 将 MyPromise 状态更改为 resolved
this.PromiseStatus = 'resolved';
}
// 更新 MyPromise 的 value
this.PromiseValue = value;
}
// executor 中的 reject 方法
let reject = reason => {
if(this.PromiseStatus === 'pending'){
// 将 MyPromise 状态更改为 rejected
this.PromiseStatus = 'rejected';
}
// 更新 MyPromise 的 value
this.PromiseValue = reason;
// 抛出错误信息
console.error(reason);
}
// 捕获,若 executor 报错,直接执行 reject
try{
executor(resolve, reject)
}catch(err) {
reject(err)
}
}
// then 方法接受两个回调,onFulfilled 为成功时的回调,onRejected 为失败时的回调
then(onFulfilled, onRejected) {
if(this.PromiseStatus=='resolved'){
onFulfilled(this.PromiseValue);
} eslse if(this.PromiseStatus=='rejected') {
onRejected(this.PromiseValue);
}
}
}

测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function test(arg) {
var p = new Promise((resolve, reject) => {
if(arg=='1') {
resolve('成功!')
}else{
reject('失败!')
}
})
console.log('test:', p);
p.then(value => {
console.log('then:', value)
}).catch(reason => {
console.log('catch:', reason)
})
}


var mp1 = new MyPromise(() => {})
var mp2 = new MyPromise((resolve, reject) => {resolve(123)})
var mp3 = new MyPromise((resolve, reject) => {reject(123)})

console.log(p1,mp1)
console.log(p2,mp2)
console.log(p3,mp3)

测试截图

复制代码到控制台试试吧~

手写 Promise 1

更新中······