promise
为什么有Promise?
-
用来解决回调地狱,代码更加简洁易维护;
setTimeout(function () { //第一层 console.log('武林要以和为贵'); setTimeout(function () { //第二程 console.log('要讲武德'); setTimeout(function () { //第三层 console.log('不要搞窝里斗'); }, 1000) }, 2000) }, 3000)
-
使控制权反转,以前的异步编程时不可信任的,你不知道它什么是时候执行了回调函数,过早还是过晚,次数多了还是少了。
promise自己注册回调,且执行回调函数时状态已经确定,回调函数只会执行一次。
什么是Promise?
Promise是js中的一个原生对象,是一种异步编程的解决方案,可以替换掉传统的回调函数解决方案。
三个状态pedding
、resolved(fulfilled)
、reject(rejected)
。
1、执行了resolve
,Promise状态会变成fulfilled
2、执行了reject
,Promise状态会变成rejected
3、Promise只以第一次为准
,第一次成功就永久
为fulfilled
,第一次失败就永远状态为rejected
4、Promise中有throw
的话,就相当于执行了reject
回调API
then
方法用来接收处理成功时响应的数据catch
方法用来接收处理失败时相应的数据。all
- 接收一个Promise数组,数组中如有非Promise项,则此项当做成功
- 如果所有Promise都成功,则返回成功结果数组
- 如果有一个Promise失败,则返回这个失败结果
race
- 接收一个Promise数组,数组中如有非Promise项,则此项当做成功
- 哪个Promise最快得到结果,就返回那个结果,无论成功失败
链式回调
1、then方法本身会返回一个新的Promise对象
2、如果返回值是promise对象,返回值为成功,新promise就是成功
3、如果返回值是promise对象,返回值为失败,新promise就是失败
4、如果返回值非promise对象,新promise对象就是成功,值为此返回值
function request(args){ // 模拟接口请求
return new Promise( (resolve,reject) =>{
setTimeout( () => {
resolve(args);
},1000)
})
}
//每隔1s输出 return Promise
request('武林要以和为贵')
.then((data)=>{
console.log(data);
return request('要讲武德');
})
.then((data)=>{
console.log(data);
return request('不要搞窝里斗')
})
.then((data)=>{
console.log(data);
})
.catch((data)=>{
console.log(data);
})
//同时输出
request('武林要以和为贵')
.then((data)=>{
console.log(data);
return '要讲武德';//没有return Promise
})
.then((data)=>{
console.log(data);
})
//另一种写法
//拿到接口1 后调接口2
request(5).then(res1 => {
console.log(res1) // 1秒后 输出 10
request(res1).then(res2 => {
console.log(res2) // 2秒后 输出 20
})
})
但是Promise最大的问题就是代码冗余,原来的异步任务被Promise封装一下,不管什么操作都用then,就会导致一眼看过去全是then…then…then…,这样也是不利于代码维护的。
aysnc/await
同步方式执行异步操作。语法糖,类似genertor
//拿到接口1 后调接口2
async function fn(){
let res1 = await request(1);
let res2 = await request(res1);
console.log(res2);
}
async
- 声明函数,表示该函数为一个异步任务,不会阻塞后面函数的执行
- async函数返回的是一个Promise对象,有无值看有无return值
await
- await关键字只能在使用async定义的函数中使用
- await后面可以直接跟一个 Promise实例对象
- await函数不能单独使用
- await可以直接拿到Promise中resolve中的数据。
如果await后面是 promise对象会造成异步函数停止执行并且等待 promise 的解决,
如果await后面是 正常的表达式则立即执行。
function sleep(second) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(' enough sleep~');
}, second);
})
}
async function awaitDemo() {
let result = await sleep(2000);
console.log("123")
console.log(result);
}
awaitDemo();// 两秒之后会被打印出来 '123'和' enough sleep~'
function sleep(second) {
setTimeout(() => {
console.log(' enough sleep~');
}, second);
}
async function awaitDemo() {
let result = await sleep(2000);
console.log("123");
}
awaitDemo();//立即输出123 两秒后输出' enough sleep~'
generator函数
next()
执行后会返回一个对象,对象中有value 和 done
两个属性
- value:暂停点后面接的值,也就是yield后面接的值
- done:是否generator函数已走完,没走完为false,走完为true
yield
:中途暂停点
-
yield + 函数:会马上执行此函数,并且该函数的执行返回值,会被当做此暂停点对象的
value
-
yield + Promise: 函数返回Promise
-
Promise+next传参:实现async/await
function* gen() { const num1 = yield request(1) const num2 = yield request(num1) const num3 = yield request(num2) return num3 } const g = gen() console.log(g.next()) // { value: Promise { <pending> }, done: false } console.log(g.next()) // { value: Promise { <pending> }, done: false } console.log(g.next()) // { value: 3, done: true } const next1 = g.next() next1.value.then(res1 => { console.log(next1) // 1秒后同时输出 { value: Promise { 2 }, done: false } console.log(res1) // 1秒后同时输出 2 const next2 = g.next(res1) // 传入上次的res1 next2.value.then(res2 => { console.log(next2) // 2秒后同时输出 { value: Promise { 4 }, done: false } console.log(res2) // 2秒后同时输出 4 const next3 = g.next(res2) // 传入上次的res2 next3.value.then(res3 => { console.log(next3) // 3秒后同时输出 { value: Promise { 8 }, done: false } console.log(res3) // 3秒后同时输出 8 // 传入上次的res3 console.log(g.next(res3)) // 3秒后同时输出 { value: 8, done: true } }) }) })