promise代表了一个异步操作的最终结果,主要是通过then方法来注册成功以及失败的情况
Promise用处:
1、主要用于异步计算
2、可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果
3、可以在对象之间传递和操作promise,帮助我们处理队列
通俗的说promise就是实现我们所期望的顺序去执行复杂代码。
解决ajax的回调地狱,为了代码的可读性可维护性,出现了Promise构造函数。
Promise的三种状态:
- pending 等待中、进行中,表示还没有返回结果;
- resolved(fulfilled) 已经完成返回了结果,可以继续往下执行;
- rejected 表示得到了结果但是并不是我们想要的,所以拒绝执行。
.then() .catch() 拿到的都是 Promise 构造函数内第一次执行的结果
const promise = new Promise((resolve, reject) => {
resolve("success1");
reject("error");
resolve("success2");
});
promise
.then(res => {
console.log("then: ", res);
}).catch(err => {
console.log("catch: ", err);
})
// then:success1
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('timer')
resolve('success')
}, 1000)
})
const start = Date.now();
promise.then(res => {
console.log(res, Date.now() - start)
})
promise.then(res => {
console.log(res, Date.now() - start)
})
//'timer'
//'success' 1001
//'success' 1002
// Promise 的 .then 或者 .catch 可以被调用多次,但这里Promise构造函数只执行一次
// promise 内部状态一经改变,并且有了一个值,
// 那么后续每次调用 .then 或者 .catch 都会直接拿到该值。
Promise 构造函数,第一个参数是函数,会立即执行,用来处理Promise的状态变化。该函数的两个参数都是可选函数,resolve函数是将状态处理为resolved成功的,reject函数是将状态处理为rejected。
new Promise(function(resolve, reject) {
if (typeof num == 'number') {
resolve();
} else {
reject();
}
}).then(function() {
console.log('参数是一个number值');
}, function() { console.log('参数不是一个number值’) }
)
Promise结合setTimeout
setTimeout不管你设定多少时间,有一个4ms的最短时间延迟,最少都要间隔4ms才运行里面的回调。而Promise的异步没有这个问题。Promise所在的异步队列优先级要高于setTimeOut。
setTimeout(() => {
console.log(7)
}, 0)
new Promise((resolve, reject) => {
console.log(3);
resolve();
console.log(4);
}).then(() => {
console.log(6)
})
console.log(5)
// 执行结果3,4,5,6,7
Promise中的then、catch、finally
.then()
1. .then() 执行结果返回一个 Promise 对象,若返回非 promise 的值也会被包裹成 promise 对象
Promise.resolve().then(() => {
return new Error('error!!!') //return Promise.resolve(new Error('error!!!'))
}).then(res => {
console.log("then: ", res)
}).catch(err => {
console.log("catch: ", err)
})
//"then: " "Error: error!!!"
2. .then() 接收两个可选函数参数,第一个是处理成功的函数,第二个是处理失败的函数。若 传入非函数参数则会发生值透传。
Promise.reject('err!!!')
.then((res) => {
console.log('success', res)
}, (err) => {
console.log('error', err)
}).catch(err => {
console.log('catch', err)
})
//'error','err!!!' reject('err!!!')会进then()的第二个参数方法内
Promise.resolve(1)
.then(2)
.then(Promise.resolve(3))
.then(console.log)
// 1 发生透传 resolve(1)直接传给最后一个then发法
3. .then 或 .catch 返回的值不能是 promise对象本身,否则会造成死循环
const promise = Promise.resolve().then(() => {
return promise;
})
promise.catch(console.err)
//Uncaught(in promise)
//TypeError: Chaining cycle detected for promise #<Promise>
.catch()
.catch 不管被连接到哪里,都能捕获上层未捕捉过的错误
.then 或 .catch 返回的值不能是 promise 本身,否则会造成死循环
.then 或者 .catch 中 return 一个 error 对象并不会抛出错误,不会被后续的 .catch 捕获
const promise = new Promise((resolve, reject) => {
reject("error");
resolve("success2");
});
promise
.then(res => {
console.log("then1: ", res);
}).then(res => {
console.log("then2: ", res);
}).catch(err => {
console.log("catch: ", err);
}).then(res => {
console.log("then3: ", res);
})
//"catch: " "error"
// 【catch不管被连接到哪里,都能捕获上层未捕捉过的错误
//"then3: " undefined
// 【catch捕获到错误后也会返回一个promise,所以后面then方法会继续执行
// 如果想要阻止后续代码继续执行,可使用 throw new Error 向外抛出错误,
// 或者使用promise的reject()。
.finally()
- .finally()不管 Promise对象最后的状态如何都会执行
- .finally()的回调函数不接受任何参数,也就是 .finally()函数中是没法知道 Promise最终的状态是 resolved还是 rejected的
- .finally() 也是返回一个 Promise对象, 最终返回的默认是 上一次的 Promise 对象值 ,不过如果抛出的是一个异常则返回异常的 Promise 对象。
Promise中的all和race
Promise.all() 接收一组异步任务,当所有异步任务执行完成之后,才可以调 .then() 。 结果数组的顺序和 Promise.all() 接收到的数组顺序一致!!!
Promise.race() 也接收一组异步任务,不同的是, race() 只取第一个先执行完的异步任务结果 ,就调 .then()。 其他异步任务仍在执行,但执行结果会被丢弃。
all和race传入的数组中如果有抛出异常的异步任务,那么只有最先抛出的错误会被 then的第二个参数或者后面的 catch捕获;但并不会影响数组中其它的异步任务的执行。