二、Promise
2.1 Promise介绍
- new Promise就可以得到一个对象,new Promise时,需要传入一个回调函数,这个回调函数是立即执行,叫执行器,这个执行器中有两个参数,分别是resolve和reject。
<script>
//Promise resolver 执行器,必须是一个函数
//执行器会立即执行
//p叫Promise对象
//默认创建的Promise有三种状态,当new出来时,处于等状态
//调用resolve可以把等待状态(pending)的promise变成成功态(fullfilled)
//调用reject可以把等待状态(pending)的promise变成失败态(rejected)
//一个Promise只能从等待到成功或者从等待到失败
//一旦成功了,就不能失败了
let p = new Promise((resolve, reject) => {
//在执行器中通常写异步代码,异步指的是定时器中的回调函数
console.log("xxx")
setTimeout(() => {
console.log("我是定时器~")
reject("没钱");//和resolve只能二选一
resolve("包包");//把等待的Promise变成一个成功的Promise
//resolve("成功的值,也叫做终值")
reject("没钱");//和resolve只能二选一
}, 2000)
});
console.log('--p', p);
setTimeout(() => {
console.log(p)
}, 3000)
</script>
用Promise重写0-100之和:
<script>
function fn(counter) {
let promise = new Promise((resolve,reject) => {
setTimeout(() => {
if (counter > 0) {
let total = 0;
for (let i = 0; i <= counter; i++) {
total += i;
}
resolve(total)
} else {
reject("你传递的数据不合法")
}
}, 3000)
})
return promise;
}
// console.log(fn(100))
//promise.then里面有2个参数,第一个拿成功的,第二个拿失败的
fn(100).then((value)=>{
console.log('--value',value);
},(reason)=>{
console.log('--reason:',reason);
})
</script>
2.2 resolve的实参问题
调用resolve,promise不一定都是成功的promise,分三种情况:
- 传递一个普通的数据,promise是成功的promise
- 传递一个p(promise),最终的promise是成功还是失败取决于p
- 传递一个thenable{then(resolve,reject){}}(大括号then小括号大括号),最终的promise是成功还是失败取决于thenable
代码演示:
<script>
const p = new Promise((resolve,reject)=>{
// thenable {then(){}} {eat(){}} : eatable
//
setTimeout(()=>{
//resolve("p的resolve")
reject("没钱")
},2000)
});
let promise = new Promise((resolve, reject) => {
// 1)参数是普通的数据
// resolve(111)
// resolve('包包')
// resolve(["a","b","c"])
// resolve({name:"ml"})
// 2)参数是promise
// 成功与否取决于参数的promise
// resolve(p)
// 3)参数是thenable 就是一个对象中有一个then函数
resolve({
then(resolve,reject){
//resolve('包包')
reject('没钱')
}
})
})
promise.then((value)=>{
console.log('--value',value);
},(reason)=>{
console.log('--reason:',reason);
})
</script>
2.3 then方法
一个promise对象,都有一个then方法,只要是一个promise,都有一个then方法,代码演示:
<script>
const p = new Promise((resolve,reject)=>{
reject("error")
})
p.then((res)=>{console.log(res);},(err)=>{console.log(err);});
p.then((res)=>{console.log(res);},(err)=>{console.log(err);});
p.then((res)=>{console.log(res);},(err)=>{console.log(err);});
p.then((res)=>{console.log(res);},(err)=>{console.log(err);});
</script>
2.4 then函数的返回值
then方法是有返回值的,它返回一个新的promise。只要then,就可以一直then
<script>
const p = new Promise((resolve,reject)=>{
reject("error")
})
//then链 then完之后,得到一个新的promise,我们要研究新的promise是成功的还是失败的
p.then((res)=>{console.log(res);},(err)=>{console.log(err);})
.then((res)=>{console.log(res);},(err)=>{console.log(err);})
.then((res)=>{console.log(res);},(err)=>{console.log(err);})
.then((res)=>{console.log(res);},(err)=>{console.log(err);});
</script>
现在我们需要研究新的promise是成功的还是失败的,新的promise是成功的还是失败的,取决于上一个then做了什么,当上一个then方法中的回调函数在执行时,新promise处于等待状态,当商业给then返回一个结果时,那这个结果就决定了新的promise的状态,情况有下面四种:[需要背会]
- 上一个then返回一个普通的值(包含undefined) 新的promise是成功的promise
- 上一个then返回一个promise,新的promise是成功还是失败取决于返回的哪个promise
- 上一个then返回一个thenable值,新的promise是成功还是失败取决于thenable是成功还是失败
- 上一个then抛出一个错误,新的promise就是失败的promise
上一个then返回一个普通的值(包含undefined)新的promise是成功的promise,代码演示:
<script>
//p成功还是失败,取决于调用的是resolve还是reject
const p = new Promise((resolve, reject) => {
resolve("success");
});
p.then((res) => {
console.log(res);
}, (err) => {
console.log(err);
}).then((res) => {
console.log(res);
}, (err) => {
console.log(err);
}).then((res) => {
console.log(res);
}, (err) => {
console.log(err);
})
</script>
上一个then返回promise,代码演示
<script>
const px = new Promise((resolve, reject) => {
setTimeout(()=>{
//resolve("px的resolve")
reject("没钱")
},2000)
});
const p = new Promise((resolve, reject) => {
resolve("success");
});
//成功或者是失败是作用于下一个then上面的
//p成功作用在了p.then上面
p.then((res) => { //p是成功的,所以走res
console.log(res); //执行这一行,输出res ,即success
return px;
}, (err) => {
console.log(err);
}).then((res) => { //p.then,return px,是失败的,所以走err
console.log(res);
}, (err) => {
console.log(err); //执行这一行,输出err,即没钱 没有返回值,默认返回undefined
}).then((res) => { //p.then.then是成功的,所以走res
console.log(res); //执行这一行,输出res,即undefined
}, (err) => {
console.log(err);
})
</script>
上一个then返回一个thenable值,新的promise是成功还是失败取决于thenable是成功还是失败,代码演示:
<script>
const p = new Promise((resolve, reject) => {
resolve("success");
});
//成功或者是失败是作用于下一个then上面的
//p成功作用在了p.then上面
p.then((res) => { //p是成功的,所以走res
console.log(res); //执行这一行,输出res ,即success
return {
then(resolve,reject){
reject("没钱")
}
};
}, (err) => {
console.log(err);
}).then((res) => { //p.then,由于上面返回reject,是失败的,所以走err
console.log(res);
}, (err) => {
console.log(err); //执行这一行,输出err,即没钱 没有返回值,默认返回undefined
}).then((res) => { //p.then.then是成功的,所以走res
console.log(res); //执行这一行,输出res,即undefined
}, (err) => {
console.log(err);
})
</script>
上一个then抛出一个错误,代码演示:
<script>
const p = new Promise((resolve, reject) => {
resolve("success");
});
p.then((res) => {
console.log(res);
// throw new Error("bad")
console.log(aaa);
}, (err) => {
console.log(err);
}).then((res) => {
console.log(res);
}, (err) => {
console.log(err);
}).then((res) => {
console.log(res);
}, (err) => {
console.log(err);
})
</script>
2.5 then的顺延
then的顺延分成2种。
-
一般写then的格式为。p.then((res)=>{console.log(res)},(err)=>{console.log(err)})
但是可以将其中一个形参改成null,如果将成功(也就是前者)改成null,那么会一直顺延下去,直到找到成功时的console.log,再进行输出,失败同理
<script> const p = new Promise((resolve, reject) => { resolve('success'); // reject("bad"); }); p.then(null,(err)=>{console.log(err)}) .then(null,(err)=>{console.log(err)}) .then(null,(err)=>{console.log(err)}) .then((res)=>{console.log(res)},(err)=>{console.log(err)})//在这一行输出了res </script> -
另外一种关于顺延的则是then,catch。then用来获取成功结果,catch用来获取失败结果
p.then((res)=>{console.log(res)}).catch((err)=>{console.log(err)})
<script> const p = new Promise((resolve, reject) => { resolve('success'); // reject("bad"); }); // catch(null,err=>{}) p.then((res)=>{ //拿成功结果 console.log(res); }).catch((err)=>{ //获取失败结果 console.log(err); }) // p.then((res)=>{console.log(res)}).catch((err)=>{console.log(err)}) </script>2.6 finally
不管promise成功还是失败,最终都会执行finally,代码如下:
<script>
const p = new Promise((resolve, reject) => {
resolve('success');
// reject("bad");
});
p.then((res)=>{console.log(res)})
.catch((err)=>{console.log(err)})
.finally(()=>{console.log("----------")})
</script>
2.7 promise的静态方法
前面学习的then,catch,finally都是promise实例上的方法,其实在Promise这个类上面,还有一些,这些方法,叫静态方法,代码如下:
<script>
let p = Promise.resolve("包包");
// 相当于
// new Promise((resolve)=>{
// resolve("包包")
// })
p.then((res)=>{
console.log("then的结果:",res)
})
</script>
<script>
let p = Promise.reject("没钱");
// 相当于
// new Promise((resolve)=>{
// reject("没钱")
// })
p.catch((err)=>{
console.log("then的结果:",err)
})
</script>
还有一个all方法,all的作用:
- 所有promise都成功后,得到所有成功后的promise结果
- 如果有一个先失败了,直接得到最先失败promise的结果
代码演示:
<script>
const p1 = new Promise((resolve,reject)=>{
setTimeout(()=>{
// resolve("p1 resolve")
reject("p1 reject")
},3000)
})
const p2 = new Promise((resolve,reject)=>{
setTimeout(()=>{
// resolve("p2 resolve")
reject("p2 reject")
},2000)
})
const p3 = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve("p3 resolve")
// reject("p3 reject")
},5000)
})
// axios.all([p1,p2])
Promise.all([p1,p2,p3]).then((res)=>{
console.log("---res:",res)
}).catch((err)=>{
console.log("---err",err)
})
</script>
还有一个方法,叫allSettled
- 获取所有的promise的结果,不管成功还是失败
<script>
const p1 = new Promise((resolve,reject)=>{
setTimeout(()=>{
// resolve("p1 resolve")
reject("p1 reject")
},3000)
})
const p2 = new Promise((resolve,reject)=>{
setTimeout(()=>{
// resolve("p2 resolve")
reject("p2 reject")
},2000)
})
const p3 = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve("p3 resolve")
// reject("p3 reject")
},5000)
})
// axios.all([p1,p2])
Promise.allSettled([p1,p2,p3]).then((res)=>{
console.log("---res:",res)
}).catch((err)=>{
console.log("---err",err)
})
</script>
还有一个方法,叫race,race是比赛的意思,作用
- 会等到第一个Promise有结果(无论这个结果是fulfilled还是rejected)
<script>
const p1 = new Promise((resolve,reject)=>{
setTimeout(()=>{
// resolve("p1 resolve")
reject("p1 reject")
},3000)
})
const p2 = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve("p2 resolve")
// reject("p2 reject")
},2000)
})
const p3 = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve("p3 resolve")
// reject("p3 reject")
},5000)
})
// axios.all([p1,p2])
Promise.race([p1,p2,p3]).then((res)=>{
console.log("---res:",res)
}).catch((err)=>{
console.log("---err",err)
})
</script>
最后一个,叫any,作用:
- 返回第一个成功的 或者 返回所有都失败了
<script>
const p1 = new Promise((resolve,reject)=>{
setTimeout(()=>{
// resolve("p1 resolve")
reject("p1 reject")
},3000)
})
const p2 = new Promise((resolve,reject)=>{
setTimeout(()=>{
// resolve("p2 resolve")
reject("p2 reject")
},2000)
})
const p3 = new Promise((resolve,reject)=>{
setTimeout(()=>{
// resolve("p3 resolve")
reject("p3 reject")
},5000)
})
// axios.all([p1,p2])
Promise.any([p1,p2,p3]).then((res)=>{
console.log("---res:",res)
}).catch((err)=>{
console.log("---err",err)
})
</script>
总结Promise的静态方法:
Promise.resolve(); //成功
Promise.reject(); //失败
Promise.all(); //要成功都成功,有一个失败就不行了
Promise.allSettled();//获取所有的promise的结果,不管成功还是失败
Promise.race(); //获取第一个Promise的结果
Promise.any(); //要失败都失败,有一个成功就返回成功的