then
最重要,最基本的是then
promise.then(
function(result) { /* handle a successful result */ },
function(error) { /* handle an error */ }
);
then的第一个参数是一个函数,它在promise被解析时运行,并接收结果。
then的第二个参数是一个函数,当promise被拒绝时运行,并接收错误。
如果我们只对成功完成感兴趣,那么我们只能为.then提供一个函数参数:
let promise = new Promise(resolve => {
setTimeout(() => resolve("done!"), 1000);
});
promise.then(alert); // shows "done!" after 1 second
catch
如果我们只对错误感兴趣,那么可以使用null作为第一个参数:.then(null, errorHandlingFunction)。或者我们可以使用.catch(errorHandlingFunction),两者完全相同:
let promise = new Promise((resolve, reject) => {
setTimeout(() => reject(new Error("Whoops!")), 1000);
});
// .catch(f) is the same as promise.then(null, f)
promise.catch(alert); // shows "Error: Whoops!" after 1 second
调用.catch(f)完全是对.then(null, f)的模拟,它只是一个简写。
finally
- finally 方法用来指定在 promise 结束时,无论结果是 fulfilled 或者是 rejected,都会执行的回调函数。这样可以避免同样的语句需要在 then() 和 catch() 中都要写一次的情况。
如果你想在 promise 执行完毕后无论其结果怎样都做一些处理或清理时,finally() 方法可能是有用的。 - finally 方法的回调函数不接受任何参数,这意味着没有办法知道前面的 Promise 状态到底是 fulfilled 还是 rejected。
这表明,finally 仅用于无论最终结果如何都要执行的情况,而不能依赖 Promise 执行结果。 - finally 方法本身无异常抛出的情况下,总是会返回原来的 Promise 对象值;若抛出异常,则返回异常的 Promise 对象。
总结
- Promise 的状态一经改变就不能再改变,也就是说一个Promise实例执行后只有一个状态,要么是resolve, 要么是reject 。resolve或reject后遇到reject或resolve会忽略该代码不执行。但是其他代码仍然会执行。
var promise = new Promise((resolve, reject) => {
resolve("success1");
console.log('123');
reject("error");
console.log('456');
resolve("success2");
});
promise
.then(res => {
console.log("then: ", res);
}).catch(err => {
console.log("catch: ", err);
})
//123
//456
//then: success1
- then 、 catch 、 finally 都会返回一个新的 promise, 所以可以链式调用。
在Promise中,返回任意一个非 promise 的值都会被包裹成 promise 对象,
例如 return 'hehe' 会被包装为return Promise.resolve('hehe')。
return 的值只会往下传给 then,无论中间是否有catch 或者 finally。
var promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("success1");
}, 1000)
});
promise
.then(res => {
console.log("then: ", res);
return 'bibi';
}).catch(err => {
console.log("catch: ", err);
return 'err';
}).finally((fin)=> {
console.log(fin);
console.log('final');
return 'haha';
}).then((res) => {
console.log(res);
console.log('final-after')
}).then((res) => {
console.log(res);
console.log('final-after2')
})
//then: success1
//undefined
//final
//bibi
//final-after
//undefined
//final-after2
- catch 可以捕捉上层错误,但是对下层错误是捕捉不到的。
var promise = new Promise((resolve, reject) => {
setTimeout(() => {
reject("error");
}, 1000)
});
promise
.then(res => {
console.log("then: ", res);
return 'bibi';
}).catch(err => {
console.log("catch: ", err);
return 'err'; // 这里返回了一个 Promise
}).then((res)=> { // 继续执行
console.log('then2', res);
return Promise.reject('error2');
}).catch((err) => { //捕捉上层错误,可以隔层捕捉,但是捕捉过的错误不能再捕捉
console.log('catch2', err);
})
//catch: error
//then2 err
//catch2 error2
Promise的.then或者.catch可以被调用多次, 但如果Promise内部的状态一经改变,并且有了一个值,那么后续每次调用.then或者.catch的时候都会直接拿到该值。
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 都会直接拿到该值。
.then或者.catch中return一个error对象并不会抛出错误,所以不会被后续的.catch捕获。
Promise.resolve().then(() => {
return new Error('error!!!')
}).then(res => {
console.log("then: ", res)
}).catch(err => {
console.log("catch: ", err)
})
//"then: " "Error: error!!!"
// 这验证了第4点和第6点,返回任意一个非 promise 的值都会被包裹成 promise 对象,
// 因此这里的return new Error('error!!!')也被包裹成了return Promise.resolve(new Error('error!!!'))。
当然如果你抛出一个错误的话,可以用下面的任意一种:
return Promise.reject(new Error('error!!!'));
// or
throw new Error('error!!!')
.then或.catch返回的值不能是 promise 本身,否则会造成死循环。.then或者.catch的参数期望是函数,传入非函数则会发生值透传。
Promise.resolve(1)
.then(2)
.then(Promise.resolve(3))
.then(console.log)
// 1
// 第一个then和第二个then中传入的都不是函数,一个是数字类型,一个是对象类型
// 因此发生了透传,将resolve(1) 的值直接传到最后一个then里。