Promise 用法
什么是Promise
Promise 是异步编程的一种解决方案。是一个容器,里面保存着未来将会发生的事
Promise 用法
Promise内部有三种状态pending
、fulfilled
、rejected
,
状态只能从pending装换到fulfilled或者到rejected,
一旦转化就不可逆转,fulfilled和rejected不能相互转化,
构造函数接收一个函数作为参数,函数立即执行,函数接收两个参数,resolve()和reject(),它们都是函数,在promise函数内部定义
console.log('Hi');
new Promise(((resolve, reject) => {
console.log('I am promise');
}));
console.log('end');
// Hi -> end -> I am promise
异步操作在参数函数中执行,如果成功,执行resolve([reason]),状态变为fulfilled状态,
如果失败执行reject([error]),状态变为rejected状态。
resolve和reject都是微任务,在本轮任务末尾执行,总是晚于本轮循环的同步任务
setTimeout(function(val) {
console.log(val)
}, 0, 2);
let promise = new Promise(function(resolve, reject) {
resolve();
console.log('Promise');
});
promise.then(function() {
console.log('resolved.');
});
console.log('Hi!');
// Promise -> Hi! -> resolved. -> 2
解析
setTimeout 为异步任务,需要等待主线程、微任务、dom操作执行完才能执行
Promise 的第一个参数立即执行,见上文,(这里是主线程)resolve(),先执行,触发微任务,需 等待主线程执行完,console.log('Promise');作为主线程第一个打印的内容,
console.log('Hi!'); 位于主线程,第二个执行。
之后主线程完,执行微任务promise.then,打印console.log('resolved.');
微任务完之后执行异步任务setTimeout, console.log(val)
Promise 实例有个then方法,用来处理promise的返回,接收两个参数
第一个参数onFulfilled(),在promise状态变为fulfilled时调用。
第二个参数onRejected() 可选,在promise状态变为rejected时调用。
then方法会返回一个Promise对象,实现链式调用
new Promise(((resolve, reject) => {
resolve(2);
})).then(val => {
console.log(val);
}).then()
Promise 实例方法catch,接收一个参数,在promise状态变为rejected时调用
let p = new Promise((resolve, reject) => {
reject(2)
}).catch(e => {
console.log(e);
});
Promise.resolve() 快速返回一个fulfilled
对象
Promise.reject() 快速返回一个rejected
对象
let p = Promise.reject(123);
// console.log(p);
p.then(result => {
console.log('then', result);
}).catch(result => {
console.log('catch', result);
});
// catch123
Promise.all() 将多个promise对象包装成一个promise对象
then 方法返回的promise状态怎么判断(划重点)
很多同学在使用promise过程中,基本模式都会,就是then方法接一个then方法的返回值不清楚,下面总结出四点,用于判断then方法的返回状态:
- 如果内部返回一个基本类型数据或者什么都不返回,状态为fulfilled
- 只要有错误抛出状态为rejected
- 如果内部返回一个promise,then返回的状态和这个promise的状态一致
- 没有执行内部方法,则继承上一个promise的状态
举例说明:
规则1: 如果内部返回一个基本类型数据或者什么都不返回,状态为fulfilled
// demo1
new Promise((resolve, reject) => {
// resolve 执行之后,状态变为fullfilled
resolve(2);
}).then(val1 => {
// 上一个promise返回fullfilled状态,执行此函数打印 val1 -> 2
console.log(val1);
}, val2 => {
// 上一个promise返回fullfilled状态, 此函数不执行
console.log(val2);
}).then(val3 => {
// 由于上一个then内部只执行 console.log(val1);,没有任何返回,所以,状态为fullfilled,执行此函数,没有返回,val3 为undefined
console.log(val3);
return 5;
}, val4 => {
// 此函数不执行
console.log(val4);
}).then(val5 => {
// 由于上一个then内部返回一个普通值5,所以,状态为fullfilled,val5为返回的值5
console.log(val5);
})
// 所以最终返回 2 -> undefined -> 5
// demo2 在demo1的基础上,第一步reject,看看返回什么
new Promise((resolve, reject) => {
// resolve 执行之后,状态变为fullfilled
reject(2);
}).then(val1 => {
// 上一个promise执行reject,状态变为rejected,此函数不执行
console.log(val1);
}, val2 => {
// 上一个promise执行reject,状态变为rejected,此函数执行,打印val2 -> 2
console.log(val2);
return 3;
}).then(val3 => {
// 由于上一个then内部return 2;在reject函数内部,和resolve函数内部同等对待,没有返回值,或者返回普通值,状态统一为fullfilled,val3 为 3
console.log(val3);
return 5;
}, val4 => {
// 解析见上,这个rejecte函数就不执行le
console.log(val4);
}).then(val5 => {
// 由于上一个then内部返回一个普通值5,所以,状态为fullfilled,val5为返回的值5
console.log(val5);
})
// 最后这个返回是 2 -> 3 -> 5
规则2: 只要有错误抛出状态为rejected
// 这个比较好理解在then的reject 或者 resolve 方法中,不论谁throw error,状态都变为rejected
Promise.resolve(2).then(val1 => {
console.log(val1);
throw Error('this is a error')
return 4;
}).then(val3 => {
// 根据规则2,前一个then函数内部,先throw Error,所以状态变为reject,此函数不执行
console.log(val3);
}, val4 => {
// 此函数执行,打印error
console.log(val4.message);
}).then(val5 => {
// 这里有回到了规则1,前一个then函数,没有返回任何值,状态为fullfiled,此函数执行
console.log('val5 ' + val5)
})
// 最后打印 2 -> this is a error -> val5 undefined
规则3: 如果内部返回一个promise,then返回的状态和这个promise的状态一致
Promise.resolve(1).then(val1 => {
console.log('val1 ' + val1);
return Promise.reject(3);
}).then(val2 => {
// 前一个then,返回一个promise,状态根据此promise定,返回的promise为rejected,此函数不执行
console.log('val2', val2);
}, val3 => {
// 此函数执行
console.log('val3 ' + val3);
})
// 打印 val1 1 -> val3 3
规则4: 没有执行内部方法,则继承上一个promise的状态
Promise.resolve(1).then().then(val2 => {
// 上一个then为空,我们看它上一个promise的状态,发现为resolve,此函数执行
console.log('val2', val2);
}, val3 => {
console.log('val3 ' + val3);
})
// 打印 val2 1
建议
尽量不在then方法写rjected
方法,而是在最后写catch
方法,then的Rejected方法不能捕获自身Fulfilled中的错误
都不写Rjected 方法,错误就能传递到catch方法中
多用then方法
在使用promise过程中,需要理清楚各个环节的状态
Promise 缺点
Then 方法会纵向拉长代码