当resolve
方法的参数是普通值或对象时,Promise
状态是直接改变的。
new Promise((resolve, reject) => { // pending -> fulfilled // resolve(基本数据类型或普通对象) resolve('promise'); // resolve({name: 'fct'}); }).then(res => { console.log("res:", res);// res 即为 promise }, err => { console.log("err:", err); })
那么当前的Promise
的状态会由传入的参数Promise
来决定,相当于状态改变权进行了移交。
const newPromise = new Promise((resolve, reject) => { // resolve("aaaaaa") reject("err message") }) new Promise((resolve, reject) => { // pending -> fulfilled resolve(newPromise); // 状态由 newPromise决定 }).then(res => { console.log("res:", res); }, err => { console.log("err:", err);// err 为err message })
会执行该then
方法, 并且由该then
方法决定后续Promise
状态。
new Promise((resolve, reject) => { // pending -> fulfilled const obj = { then: function(resolve, reject) { // resolve("resolve message"); reject("reject message"); } } resolve(obj) }).then(res => { console.log("res:", res); }, err => { console.log("err:", err);// err 为 reject message })
then
方法本身也是有返回值的, 它的返回值是Promise
,因此可以链式调用。
传入then
方法的回调函数,默认是返回 undefined
。
同一个Promise
可以多次调用then
方法,当我们的resolve
方法被回调时, 所有的then
方法传入的回调函数都会被调用。
const promise = new Promise((resolve, reject) => { resolve("hahaha") }) promise.then(res => { console.log("res1:", res) // 输出:'res1: hahaha' }) promise.then(res => { console.log("res2:", res) // 输出:'res2: hahaha' }) promise.then(res => { console.log("res3:", res) // 输出:'res3: hahaha' })
普通值:数值、字符串、普通对象、undefined等。
当返回值是一个普通值时,那么这个值就会作为一个新的Promise的resolve值。
promise.then(res => { return "aaaaa"; // 相当于: // return Promise.resolve("aaaaa"); // return new Promise(resolve => resolve('aaaaa')); }).then(res => { console.log("res:", res);// 输出:'res: aaaaa' return "bbbbbb" })
返回一个Promise,那么后续状态是由返回的新Promise决定。
promise.then(res => { return new Promise((resolve, reject) => { setTimeout(() => { resolve(111111) }, 3000); }) }).then(res => { console.log("res:", res); // res: 111111 })
会执行该对象上的then方法,根据执行结果返回不同状态
promise.then(res => { return { then: function (resolve, reject) { resolve(222222) } } }).then(res => { console.log("res:", res); // res: 222222 })
普通用法不再赘述,这里讨论catch
方法中传入的回调函数的返回值,情况和then
方法的回调函数一样。
将某个值转成Promise成功的返回值,可以使用Promise.resolve方法。
function foo() { const obj = { name: "fct" } return new Promise((resolve) => { resolve(obj); }) } foo().then(res => { console.log("res:", res); }) // 使用类方法:Promise.resolve // resolve方法参数传入普通的值 const promise = Promise.resolve({ name: "fct" }) // 相当于 const promise2 = new Promise((resolve, reject) => { resolve({ name: "why" }) })
根据传递的不同类型参数(如返回Promise、返回带then方法的对象),后续的状态会有不同的变化,就如前文所说。
const promise = Promise.reject("rejected message") // 相当于 const promise2 = new Promsie((resolve, reject) => { reject("rejected message") })
注意:reject
方法传递什么参数值,都是一样。
const promise = Promise.reject(new Promise(() => { })); // const promise = Promise.reject({ then() { } }); promise.then(res => { console.log("res:", res) }).catch(err => { console.log("err:", err); // err: Promise { <pending> } // console.log("err:", err); // err: { then: [Function: then] } })
因为all
方法有一个缺陷:当有其中一个 Promise 变成 reject 状态时,all
方法返回的新Promise就会立即变成对应的 reject 状态。
那么对于处于resolved、以及依然处于pending状态的Promise,我们是获取不到对应的结果的;
在ES11 (ES2020)中,添加了新的 API: Promise.allSettled
。
该方法会在所有的Promise都有结果(settled ),无论是 fulfilled,还是reject时,才会有最终的状态;并且这个Promise的结果一定是 fulfilled 的;
// 创建多个Promise const p1 = new Promise((resolve, reject) => { setTimeout(() => { resolve(11111) }, 1000); }) const p2 = new Promise((resolve, reject) => { setTimeout(() => { reject(22222) }, 2000); }) const p3 = new Promise((resolve, reject) => { setTimeout(() => { resolve(33333) }, 3000); }) // allSettled Promise.allSettled([p1, p2, p3]).then(res => { console.log(res); /* [ { status: 'fulfilled', value: 11111 }, { status: 'rejected', reason: 22222 }, { status: 'fulfilled', value: 33333 } ] */ }).catch(err => { console.log(err); })
any
方法是ES12中新增的方法,和race
方法是类似的:
any
方法会等到一个fulfilled状态,才会决定新Promise的状态;// 创建多个Promise const p1 = new Promise((resolve, reject) => { setTimeout(() => { // resolve(11111) reject(1111) }, 1000); }) const p2 = new Promise((resolve, reject) => { setTimeout(() => { reject(22222) }, 500); }) const p3 = new Promise((resolve, reject) => { setTimeout(() => { // resolve(33333) reject(3333) }, 3000); }) // any方法 Promise.any([p1, p2, p3]).then(res => { console.log("res:", res); }).catch(err => { // console.log("err:", err) // err: AggregateError: All promises were rejected console.log("err:", err.errors); // err: [ 1111, 22222, 3333 ] })