属性和方法
Promise 构造函数接受一个函数作为参数,该函数的两个参数分别是 resolve 和 reject。
Promise 有两个内置属性,[[PromiseStatus]] 和 [[PromiseValue]]。
- [[PromiseStatus]]:Promise 对象的状态,这个属性可以为三个值:resolved、pending 和 rejected,状态一旦改变为 resolved 或者 rejected 就不能够再变回 pending,resolved 和 rejected 也不能够互相转化。
- [[PromiseStatus]]:是 Promise 的值,这个值为传入 resolve() 方法和 reject() 方法中的参数。
Promise 对象有两个方法,then 方法和 catch 方法。
- then():可以接受两个回调函数作为参数。第一个回调函数在 Promise 对象的状态变为 resolved 时调用,第二个回调函数在 Promise 对象的状态变为 rejected 时调用。这两个函数都接受 [[PromiseStatus]] 作为参数。
- catch():.then(null, rejection) 的别名,用于指定发生错误时的回调函数。
Promise 构造函数的方法:
- Promise.resolve():接受一个参数,创建一个新的 Promise 对象,[[PrmiseStatus]] 为 resolved,[[PromiseValue]] 为传入的参数。
- Promise.reject():类似 Promise.resolve()。
- Promise.all():接受一个数组作为参数,将其中的多个 Promise 对象包装成一个新的 Promise 对象。如果数组中某个元素不是 Promise 对象,那么将这个参数传入 Promise.resolve() 方法转换为 Promise 对象。只要有一个 Promise 对象的状态变为 rejected,新 Promise 状态就会立刻变为 rejected,只有当所有的 Promise 对象状态都变为 resolved 时,新 Promise 对象的状态才会变为 resolved。
- Promise.race():类似 Promise.all,只要有一个 Promise 对象的状态变为 resolved,新 Promise 状态就会立刻变为 resolved,只有当所有的 Promise 对象状态都变为 rejected 时,新 Promise 对象的状态才会变为 rejected。
基本用法
new Promise((resolve, reject) => {
if (condition) {
resolve(data)
} else {
reject(err)
}
})
.then((data) => {
//do something
}, (err) => {
//do something
})
值与状态的传递
下面讨论一些特殊情况下值与状态的传递。
链式调用
.then() 方法和 .catch() 方法都会返回一个新的 Promise 对象,这个对象与原 Promise 对象是不同的。
如果 .then() 方法和 .catch() 方法没有对 Promise 的事件进行处理,那么新的 Promise 将会继承原 Promise 对象的 [[PromiseStatus]] 和 [[PromiseValue]]。
例如以下代码将会打印 1。第一个 then() 没有对事件进行任何处理,因此第二个 then() 可以拿到原 Promise 传出的 1。
new Promise((resolve, reject) => {
reject(1);
})
.then(() => {})
.then(() => {},
(n) => {console.log(n);});
如果 .then() 方法和 .catch() 方法对事件进行了处理,那么新的 Promise 对象 [[PromiseStatus]] 将会是 resolved,[[PromiseValue]] 将会是 undefined。
传入 Promise 作为参数
当 resolve() 方法或者 reject() 方法传入的参数为一个 Promise 对象时会等待其中这个 Promise 对象的状态改变,然后才返回。返回的 Promise 对象的 [[PromiseStatus]] 和 [[PromiseValue]] 都与内层 Promise 相同。例如以下代码将在一秒后打印 '1 reject'。
new Promise((resolve, reject) => {
resolve(
new Promise((resolve, reject) => {setTimeout(() => {reject(1);}, 1000);})
);
})
.then((e) => {console.log(e + ' resolve');},
(e) => {console.log(e + ' reject');});
需要注意的是,上文说的“等待其中这个 Promise 对象的状态改变”并不是真的说代码会停止在 resolve 处不再执行,实际上代码会继续向下执行并且暂时返回一个状态为 pending 的 Promise 对象,等待状态的改变。例如以下代码将立即打印 2,然后再一秒后打印 '1 reject'
new Promise((resolve, reject) => {
resolve(
new Promise((resolve, reject) => {setTimeout(() => {reject(1);}, 1000);})
);
//↓
console.log(2);
//↑
})
.then((e) => {console.log(e + ' resolve');},
(e) => {console.log(e + ' reject');});
resolve()方法和 reject() 方法只能够调用一次
前文说到 Promise 的状态只能够改变一次,实际上是 resolve() 方法和 reject() 方法只能够调用一次。例如:
new Promise((resolve, reject) => {
resolve(
new Promise(
//↓
() => {setTimeout(() => {reject(1);}, 1000);}
//↑
)
);
})
.then((e) => {console.log(e + ' resolve');},
(e) => {console.log(e + ' reject');});
这段代码不会打印任何内容,这段代码与前一段的不同之处在于箭头处调用的 reject() 方法是外层 Promise 的 reject() 方法。由于先调用了 resolve() 方法,所以这个 reject() 方法是无效的,另外,resolve() 方法又在等待内部的 Promise 改变状态。因此这个 Promise 对象会一直处于 pending 状态。
Promise.all() 和 Promise.race()
以 Promise.all() 为例,Promise.race() 反之。
resolved
只要有一个 Promise 对象调用 reject(),新 Promise 状态就会立刻变为 rejected,返回的 [[PromiseValue]] 为最先调用 reject 方法的 [[PromiseValue]]。例如以下代码将会立刻打印 [object Promise] reject,然后报错。
Promise.all([
new Promise((resolve, reject) => {
setTimeout(() => {reject(1);}, 1000);
}),
new Promise((resolve, reject) => {
setTimeout(() => {resolve(2);}, 2000);
}),
new Promise((resolve, reject) => {
//↓
reject(new Promise((resolve, reject) => {setTimeout(() => {reject(3)}, 5000);}));
//↑
})
]).then((n) => {console.log(n + ' resolve');}, (n) => {console.log(n + ' reject');});
第三个 Promise 的 reject() 方法中传入的 Promise 对象的回调函数依然会被执行,但是 .all() 方法并不会等待内部 Promise 的状态改变,而是直接将返回的 Promise 对象的状态改为 rejected。而且内部 Promise 的状态也不会被传出来,而是因为没有处理而抛出错误。同理,将箭头处的 reject 改为 resolve,打印的依然会立刻打印 [object Promise] reject。再同理,以下代码依然会立刻打印 [object Promise] reject。
Promise.all([
new Promise((resolve, reject) => {
setTimeout(() => {reject(1);}, 1000);
}),
new Promise((resolve, reject) => {
setTimeout(() => {resolve(2);}, 2000);
}),
new Promise((resolve, reject) => {
reject(new Promise((resolve, reject) => {resolve(3)}));
})
]).then((n) => {console.log(n + ' resolve');}, (n) => {console.log(n + ' reject');});
rejected
只有当内部所有的 Promise 都调用了 resolve() 方法时,返回的 Promise 才会将状态改变为 resolved,其 [[PromiseValue]] 为所有 [[PromiceValue]] 组成的数组。例如以下代码将在 5 秒后打印 [1, 2, 3]。
Promise.all([
new Promise((resolve, reject) => {
setTimeout(() => {resolve(1);}, 1000);
}),
new Promise((resolve, reject) => {
setTimeout(() => {resolve(2);}, 2000);
}),
new Promise((resolve, reject) => {
setTimeout(() => {resolve(3);}, 5000);
})
]).then((n) => {console.log(n);}, (n) => {console.log(n);});
而对于传入 Promise 对象作为参数的情况处理方式又有不同,外部 Promise 对象会等待内部的 Promise 对象状态全部改变为 resolved,之后才会改变状态为 resolved。例如以下代码将在 5 秒后打印 '3 reject'。虽然 resolve() 方法已经被调用了,但是还是会等待它的状态改变。
Promise.all([
new Promise((resolve, reject) => {
setTimeout(() => {resolve(1);}, 1000);
}),
new Promise((resolve, reject) => {
setTimeout(() => {resolve(2);}, 2000);
}),
new Promise((resolve, reject) => {
resolve(new Promise((resolve, reject) => {setTimeout(() => {reject(3)}, 5000);}));
})
]).then((n) => {console.log(n + ' resolve');}, (n) => {console.log(n + ' reject');});