知识梳理
promise:
ES6原生提供了Promise对象
它是异步编程的一种解决方案
就像是一个容器保存着某个未来才会结束的事件的结果(即可以获取异步操作的消息)
promise对象是一个构造函数,用于生成Promise实例
特点:
1.对象状态不受外界影响,只有异步操作的结果才能决定当前是哪一种状态。
三种状态:pending(进行中)、fulfilled(已成功)、rejected(已失败)
2.状态一旦改变就不会再变,pending-fulfilled->resolve,pending-rejected->reject
(实例生成以后,用then方法分别指定resolved状态和rejected状态的回调函数)
优点:
异步操作将以同步操作的流程表达出来,避免了层层嵌套的回调函数
Promise对象提供了统一的接口,使得控制异步操作更加容易
链式操作:可以在then中继续写Promise对象并返回,然后继续调用then来进行回调操作
缺点:
无法取消,一旦新建就会立即执行,无法中途取消
若不设置回调函数,promise内部会抛出错误,不会反映到外部
当处于pending状态时,无法得知当前进展到哪一阶段
用法:
promise.then(成功回调函数,失败回调函数)
promise.then(成功回调函数).catch(失败回调函数)
promise.then(成功回调函数).catch(失败回调函数).finally(成功失败都执行的函数)
promise.all([a1,a2,a3])
promise.race([a1,a2,a3])
promise.resolve()
promise.reject()
promise.try()
案例分析
1.基本用法
function getNumber(){
return new Promise(function(resolve,reject){
setTimeout(()=>{
var num = Math.ceil(Math.random()*10)
if(num > 5){
resolve(num)
}else{
reject('数字太大')
}
},2000)
})
}
// 写法一,then里面两个回调函数,函数一:成功回调函数,函数二:失败回调函数
getNumber().then(
(data)=>{
console.log('resolved') // resolved
console.log(data) // 对应的数字
},
(res)=>{
console.log('reject') // reject
console.log(res) // '数字太大'
},
)
// 写法二,then里面:成功回调函数,catch里面:失败回调函数
getNumber()
.then(
(data)=>{
console.log('resolved') // resolved
console.log(data) // 对应的数字
}
)
.catch(
(res)=>{
console.log('reject') // reject
console.log(res) // '数字太大'
}
)
2.回调函数与Promise对比
// 回调函数写法
function runAsync(callback){
setTimeout(function(){
console.log('执行完成');
callback('随便什么数据');
}, 2000);
}
runAsync(function(data){
console.log(data);
});
// Promise写法(使用promise时一般包在一个函数中,需要的时候运行这个函数,否则我们只是new一个对象,不用调用就已经执行)
function runAsync(){
var p = new Promise(function(resolve,reject){
setTimeout(function(){
console.log("执行完成")
resolve("随便什么数据")
},2000)
})
return p
}
runAsync().then(function(data){ // then接收一个函数,会拿到在runAsync中调用resolve时传的参数,执行成功的回调
console.log(data)
})
3.Promise.all()
【谁跑的慢以谁为准】执行回调,此时返回值组成一个数组,传递给回调函数
只要其中一个被rejected,状态就变成rejected,第一个rejected的实例的返回值会传递给回调函数
const p1 = new Promise((resolve, reject) => {
resolve('hello');
})
.then(result => result)
.catch(e => e);
const p2 = new Promise((resolve, reject) => {
throw new Error('报错了');
})
.then(result => result)
.catch(e => e);
// 若作为参数的Promise实例自己定义了catch方法,若它一旦被rejected就不会再出发Promise.all()的catch方法
Promise.all([p1,p2]).then(
result=>console.log(result)
).catch(
e=>console.log(e) // ["hello", Error: 报错了]
)
4.Promise.race()
【谁跑得快以谁为准】
只要其中一个实例先改变状态,状态就跟着改变
将率先改变的Promise返回值传递给回调函数
const p = Promise.race([
fetch('/resource-that-may-take-a-while'),
new Promise(function (resolve, reject) {
setTimeout(() => reject(new Error('request timeout')), 5000)
})
]);
p
.then(console.log)
.catch(console.error);
5.Promise.reject()
// Promise.reject(reason)方法也会返回一个新的 Promise 实例,该实例的状态为rejected
const p = Promise.reject('出错了');
// 等同于
const p = new Promise((resolve, reject) => reject('出错了'))
p.then(null, function (s) {
console.log(s) // 出错了
});
6.Promise.resolve(),将现有对象转为 Promise 对象
Promise.resolve('foo')
// 等价于
new Promise(resolve => resolve('foo'))
7.Promise.try()
不知道或不想区分,函数是同步还是异步操作,但是想用Promise来处理
// 一:
const f = () => console.log('now');
Promise.resolve().then(f);
console.log('next')
// next now
// 二:让同步函数同步执行,异步函数异步执行
const f = () => console.log('now')
(async () => f())();
console.log('next');
// now next
const f = () => console.log('now');
(
()=>new Promise(
resolve => resolve(f())
)
)();
console.log('next')
// now next
const f = () => console.log('now');
Promise.try(f);
console.log('next')
网友评论