JavaScript异步 Promise、async/await、generator

promise

为什么有Promise?

  1. 用来解决回调地狱,代码更加简洁易维护;

    setTimeout(function () {  //第一层
        console.log('武林要以和为贵');
        setTimeout(function () {  //第二程
            console.log('要讲武德');
            setTimeout(function () {   //第三层
                console.log('不要搞窝里斗');
            }, 1000)
        }, 2000)
    }, 3000)
    
    
  2. 使控制权反转,以前的异步编程时不可信任的,你不知道它什么是时候执行了回调函数,过早还是过晚,次数多了还是少了。
    promise自己注册回调,且执行回调函数时状态已经确定,回调函数只会执行一次。

什么是Promise?

Promise是js中的一个原生对象,是一种异步编程的解决方案,可以替换掉传统的回调函数解决方案。

三个状态peddingresolved(fulfilled)reject(rejected)

1、执行了resolve,Promise状态会变成fulfilled

2、执行了reject,Promise状态会变成rejected

3、Promise只以第一次为准,第一次成功就永久fulfilled,第一次失败就永远状态为rejected

4、Promise中有throw的话,就相当于执行了reject

回调API

  1. then方法用来接收处理成功时响应的数据
  2. catch方法用来接收处理失败时相应的数据。
  3. all
    • 接收一个Promise数组,数组中如有非Promise项,则此项当做成功
    • 如果所有Promise都成功,则返回成功结果数组
    • 如果有一个Promise失败,则返回这个失败结果
  4. 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 {  }, done: false }
    console.log(g.next()) // { value: Promise {  }, 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 }
        })
      })
    })
    

你可能感兴趣的:(前端)