Promise
-
一个容器,一个保存着某个未来才会结束的事件的结果。
-
有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。一旦状态改变,就不会再变。
const p = new Promise((resolve, reject) => {
resolve("ok")
throw new Error("报错啦")
})
p.then(res => console.log("then res:", res)).catch(err => console.log("catch err:", err))
// then res: ok
-
状态的变化有两种:1. pending -> fulfilled 2. pending -> rejected
-
只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
-
结果是不会改变的,不会同时走 resolve() 和 reject() 的!
- 调用 resolve 或 reject 不会终结 Promise 的参数函数的执行。
new Promise(function(resolve, reject) {
resolve("resolve")
console.log(1)
}).then(r => {
console.log(r)
})
// 1
// resolve
立即 resolved 的 Promise 是在本轮事件循环的末尾执行,总是晚于本轮循环的同步任务。
一般来说,调用resolve或reject以后,Promise 的使命就完成了,后继操作应该放到then方法里面,而不应该直接写在resolve或reject的后面。所以,最好在它们前面加上return语句,这样就不会有意外。
-
resolve() 的作用:将状态 pending -> fulfilled , 在异步操作成功时调用,并将异步操作的结果,作为参数传递出去。
-
reject() 的作用:将状态 pending -> rejected , ,在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
- “Promise 会吃掉错误”:Promise 内部的错误不会影响到 Promise 外部的代码(Promise 对象抛出的错误不会传递到外层代码,即不会有任何反应。)。
const fn = function() {
return new Promise((resolve, reject) => {
resolve(x+1)
})
}
fn().then(res => console.log("res:", res)) // 没有捕获处理错误的噢!
setTimeout(() => console.log("继续"), 3000)
// 报错 Uncaught (in promise) ReferenceError: x is not defined
// 继续
抛出错误,3秒后,打印“继续”
Promise.prototype.then() 分别指定 resolved 状态和 rejected 状态的回调函数
then() 是定义在原型对象 Promise.prototype 上的,返回一个新的 Promise 实例,为 Promise 实例添加状态改变时的回调函数。可以采用链式写法。
- 两个参数:第一个参数是 resolved 状态的回调函数,第二个参数是 rejected 状态的回调函数,它们都是可选的。
new Promise((resolve, reject) => {
reject('出错啦')
}).then(res => console.log("res", res), err => console.log("err", err))
- 链式写法,回调函数依次被调用。
Promise.prototype.catch() 用于指定发生错误时的回调函数
catch() 是 then(null, reject) 或 then(undefined, reject) 的别名。catch() 返回一个 Promise 对象。
new Promise((resolve, reject) => {
reject(21)
}).then(res => console.log("res:", res)).catch(err => console.log("catch err:", err))
// catch err: 21
// 等同于:
new Promise((resolve, reject) => {
reject(21)
}).then(res => console.log("res:", res)).then(null, err => console.log("then err:", err))
// then err: 21
- 如果异步操作抛出错误,状态会变成 rejected , 就会调用 catch() 指定的回调函数。
const p = new Promise((resolve, reject) => {
throw new Error('出错啦')
})
p.catch(err => console.log(err))
以上代码等同于以下的两种写法:
// 写法一:
const p = new Promise((resolve, reject) => {
try {
throw new Error("出错啦")
}catch(e) {
reject(e)
}
})
p.catch(err => console.log(err))
// 写法二:
const p = new Promise((resolve, reject) => {
reject(new Error("出错啦"))
})
p.catch(err => console.log(err))
reject() 的作用:抛出错误。
- then() 指定的回调函数如果运行中抛出错误,也会被 catch() 捕获到。
-
Promise 对象的错误具有“冒泡”的性质,错误与会一直往后传递,直至被捕获。
-
new Promise(...).catch(...).then(...)
:
catch() 只会捕获到前一个 Promise 抛出的错误,没有错误的话会跳过 catch() 继续执行后边的 then() 。如果在后边的 then() 中抛出了错误,这个错误无法捕获到(与 then() 前边的 catch() 无关了),也不会传递到外层。
const p = new Promise((resolve, reject) => {
reject(new Error('出错啦'))
})
p.catch(err => console.log("err:", err)).then(res => console.log("状态:resolved"), err => console.log("状态:rejected"))
Promise.prototype.finally() 总会执行指定的回调函数(不论 Promise 的最终状态)
new Promise((resolve, reject) => {}).finally(() => {
console.log("一直存在")
})
// 等同于
new Promise((resolve, reject) => {}).then(res => {
console.log("一直存在")
return res
}, err => {
console.log("一直存在")
throw err
})
-
回调函数不接受任何参数
-
finally() 总是会返回原来的值
// 实现:
Promise.prototype.finally = function(callback) {
let p = this.constructor;
return this.then(
value => p.resolve(callback()).then(() => value),
reason = p.resolve(callback()).then(()=> {throw reason})
)
}
// resolve 的值是 2
Promise.resolve(2).finally(() => {})
// resolve 的值是 undefined
Promise.resolve(2).then(() => {}, () => {})
// reject 的值是 undefined
Promise.reject(3).then(() => {}, () => {})
// reject 的值是 3
Promise.reject(3).finally(() => {})
Promise.resolve() 将现有对象转为 Promise 对象
Promise.resolve('foo')
// 等价于
new Promise(resolve => resolve('foo'))
- 参数是一个 Promise 实例,Promise.resolve() 原封不动返回这个实例。
const p = new Promise(resolve => resolve('foo'))
const p2 = Promise.resolve(p)
p === p2 // true
- 参数是一个 thenable 对象(具有 then 方法的对象),Promise.resolve() 会将这个对象转为 Promise 对象,然后立即执行这个对象的 then() 方法。
const thenable = {
then: (resolve, reject) => {
resolve(42)
}
}
const p = Promise.resolve(thenable)
p.then((res) => console.log(res)) // 42
- 参数不是 thenable 对象或者不是一个对象(如 42,'foo'等),Promise.resolve() 会返回一个新的 Promise 对象,状态是 resolved 。
const p = Promise.resolve('foo')
p.then(res => console.log('res', res), err => console.log('err', err)) // res foo
- 不带参数,Promise.resolve() 直接返回一个 resolved 状态的 Promise 对象。
立即resolve()的 Promise 对象,是在本轮“事件循环”的结束时执行,而不是在下一轮“事件循环”的开始时。
setTimeout(function () {
console.log('three');
}, 0);
Promise.resolve().then(function () {
console.log('two');
});
console.log('one');
// one
// two
// three
setTimeout(fn, 0)在下一轮“事件循环”开始时执行。
Promise.reject() 返回一个新的状态为 rejected 的 Promise 实例
-
返回的是一个新的 Promise 实例。
-
参数原封不动地作为reject的理由,变成后续方法的参数。如:
Promise.reject('出错啦').catch(e => console.log('e', e)) // e 出错啦
Promise.all() 将多个 Promise 实例包装成一个新的 Promise 实例
只适用所有异步操作成功的情况,如果有一个异步操作失败,都无法进行下一步操作。
异步操作成功,是不会抛出错误的意思,并非是 状态 rejected 。
const p = Promise.all([p1, p2, p3]);
- 接受一个数组作为参数,数组成员都是 Promise 实例。如果成员不是 Promise 实例,会先调用 Promise.resolve() 将其转为 Promise 实例。
参数可以不是数组,但必须具有 Iterator 接口,且返回的每个成员都是 Promise 实例。
- p 的状态由 p1 、p2 、p3 决定:
-
只有 p1 、p2 、p3 的状态都变成 fulfilled , p 的状态才会变成 fulfilled , 此时 p1 、p2 、p3 的返回值组成一个数组传递给 p 的回调函数。
-
只要 p1 、p2 、p3 任意一个被 rejected , p 的状态就是 rejected , 此时第一个被 reject 的实例的返回值会传递给 p 的回调函数。
总结:只有 p1 、p2 、p3 的状态有被改变,才会调用 Promise.all 方法后面的回调函数。
- 如果作为参数的 Promise 实例,自己定义了 catch 方法,那么它一旦被 rejected , 并不会触发 Promise.all() 的 catch 方法。
// p1 resolved
const p1 = new Promise((resolve, reject) => resolve('hi')).then(res => {
console.log("p1 res :", res)
return res
}).catch(err => {
console.log("p1 err :", err)
return err
})
// p2 先 rejectd -> p2 有 catch() , 执行后,返回一个新的 Promise 实例, p2 指向了这个新实例,状态为 resolved
// rejected : catch -> 抛出错误:报错啦 => 返回一个新的 Promise 对象 状态: resolved
const p2 = new Promise((resolve, reject) => {throw new Error('报错啦')}).then(res => {
console.log("p2 res :", res)
return res
}).catch(err => {
console.log("p2 err :", err)
return err
})
// resolved
Promise.all([p1, p2]).then(res => console.log('Promise.all res :', res)).catch(err => console.log('Promise.all err :', err))
// p1 res : hi
// p2 err : [Error: 报错啦]
// Promise.all res : [ 'hi', [Error: 报错啦] ]
如果 p2 没有 catch 方法,就会调用 Promise.all() 的 catch 方法,输出结果就不同了:
const p2 = new Promise((resolve, reject) => {throw new Error('报错啦')}).then(res => {
console.log("p2 res :", res)
return res
})
// p1 res : hi
// Promise.all err : [Error: 报错啦]
Promise.race() 将多个 Promise 实例包装成一个新的 Promise 实例
const p = Promise.race([p1, p2, p3]);
参数同 Promise.all() , 与其不同点是 p 状态的改变:
-
只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例(其实就是第一个 Promise 改变状态)的返回值,就传递给p的回调函数。
-
Promise.all() 和 Promise.race() 传入空数组[] 作为参数:
-
Promise.all() 传入一个空数组,会立即完成
-
Promise.race() 传入一个空数组,会被挂住,且不会决议(状态:pending)。
总结:p1、p2、p3 任意一个实例状态改变,p 的状态就跟着变了。
Promise.allSettled() 确定一组异步操作是否都结束了(不论操作成功或失败)
const p = Promise.allSettled([p1, p2, p3]);
-
Promise.allSettled() 接受一个数组作为参数,数组每个成员皆为 Promise 对象。返回一个新的 Promise 对象。
-
状态变化:只有 p1, p2, p3 所有 Promise 对象都发生状态变更(不论是 fulfilled / rejected),p (返回的 Promise 对象)才会发生状态变更。
-
Promise.allSettled() 返回的新的 Promise 实例,一旦状态发生变更,状态总是 fulfilled ,不会是 rejected 的。
- 状态变为 fulfilled 后,它的回调函数会接收一个数组作为参数,数组成员对应前面数组的每一个 Promise 对象,对象的格式是固定的:
const resolved = Promise.resolve(42)
const rejected = Promise.reject(-1)
const p = Promise.allSettled([resolved, rejected])
p.then(res => console.log(res))
// [ { status: 'fulfilled', value: 42 }, { status: 'rejected', reason: -1 } ]
Promise.any() 将多个 Promise 实例包装成一个新的 Promise 实例
const p = Promise.any([p1, p2, p3]);
-
Promise.any() 接受一个数组作为参数,数组每个成员皆为 Promise 对象。返回一个新的 Promise 对象。
-
p 状态改变:
-
p1, p2, p3 只要有一个状态变为 fulfilled , p 的状态:fulfilled
-
p1, p2, p3 都变成 rejected , p 的状态:rejected
const resolved = Promise.resolve(21)
const rejected = Promise.reject(-1)
Promise.any([resolved, rejected]).then(res => console.log("res:", res), err => console.log("err:", err))
// res: 21
- 与 Promise.race() 不同处在于某一个参数 Promise 的状态变为了 rejected 的继续操作:
-
Promise.race() 某一个参数 Promise 变成了 rejected 就结束了。
-
Promise.any() 必须等到所有参数 Promise 变成 rejected 状态才会结束。
标签:ES6,resolve,console,err,res,Promise,reject From: https://www.cnblogs.com/4shana/p/17865522.htmlPromise.any() 参数 Promise 但凡有一个状态变为了 fulfilled ,都不会被 catch() 捕获到。