备战-promise、async、await

203 阅读4分钟

promise概念

我们先从定义入手,ES6中promise是什么,我们用它来干什么?

Promise 是异步编程的一种解决方案: 从语法上讲,promise是一个对象,从它可以获取异步操作的消息;从本意上讲,它是承诺,承诺它过一段时间会给你一个结果。

promise有三种状态:

  • pending(等待态)
  • fulfiled(成功态)
  • rejected(失败态)

状态一旦改变,就不会再变。创造promise实例后,它会立即执行。

promise是用来解决两个问题的:

  • 回调地狱,我们看一个简单的函数嵌套函数,这样还是只有一层,多了的话嵌套起来会比较麻烦也难以维护我们就可以使用promise解决
    function fn1(a, fn2) {
        if (a > 10) {
            fn2()
        }
    }
    fn1(11, function() {
        console.log('this is a callback')
    })
    
  • promise可以支持多个并发的请求,获取并发请求中的数据

promise用法

Promise构造函数

Promise是一个构造函数,自己身上有all、resolve、reject这几个方法,原型上有then、catch供我们实现嵌套。我们还是像往常一样先创建一个简单的案例然后慢慢分析实现。

let promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log('执行完成');
        resolve('接收成功执行');
    }, 1000);
})

这边我们要注意一下Promise构造函数的参数,是一个函数该函数参数为resolveresolve

then、catch方法

Promise生成的对象用then方法对应resolve,这样的条件嵌套更加方便维护而且更加明了,同样的catch对应reject,而且catch方法会捕获错误而不会因为代码问题终止程序,我们看一个实际异步案例

    let p = new Promise((resolve, reject) => {
        //做一些异步操作
      setTimeout(function(){
            var num = Math.ceil(Math.random()*10);
            if(num<=5){
                resolve(num);
            }
            else{
                reject('数字太大了');
            }
      }, 1000);
    });
    p.then((data) => {
            console.log(data);
            return data
        }
    ).catch((err) => {
            console.log(err);
        }
    )
    .then((data) => {
        console.log(data);
    })

Promise的all方法

这边就简单提及一下Promise的all方法可以综合promise对象生成一个新的对象,然后要all中所有对象都成功则成功。

手写Promise

创建Promise类

小编这边简单的实现一下手写Promise,包括执行器包括的resolve,reject方法,then、catch方法,感受一下内置流程

// 创建promise类
class Promise {
    constructor (executor){
        //默认状态是等待状态
        this.status = 'panding';
        this.value = undefined;
        this.reason = undefined;
        //存放成功的回调
        this.onResolvedCallbacks = [];
        //存放失败的回调
        this.onRejectedCallbacks = [];
        let resolve = (data) => {//this指的是实例
            if(this.status === 'pending'){
                this.value = data;
                this.status = "resolved";
                this.onResolvedCallbacks.forEach(fn => fn());
            }
 
        }
        let reject = (reason) => {
            if(this.status === 'pending'){
                this.reason = reason;
                this.status = 'rejected';
                this.onRejectedCallbacks.forEach(fn => fn());
            }
        }
        try{//执行时可能会发生异常
            executor(resolve,reject);
        }catch (e){
            reject(e);//promise失败了
        }
       
    }
}

实现then方法

    then(onFulFilled, onRejected) {
    if (this.status === 'resolved') { //成功状态的回调
      onFulFilled(this.value);
    }
    if (this.status === 'rejected') {//失败状态的回调
      onRejected(this.reason);
    }
  }

promise常见考题

执行顺序

const promise = new Promise((resolve, reject) => {
  console.log(1)
  resolve()
  console.log(2)
})
promise.then(() => {
  console.log(3)
})
console.log(4)

这边我们注意promise对象是创建及执行,而then方法是异步的。


resolve、reject方法

const promise = new Promise((resolve, reject) => {
  resolve('success1')
  reject('error')
  resolve('success2')
})

promise
  .then((res) => {
    console.log('then: ', res)
  })
  .catch((err) => {
    console.log('catch: ', err)
  })

构造函数中的 resolve或reject只有第一次执行有效,多次调用没有任何作用,promise 状态一旦改变则不能再变,这边也提及一点.then 或 .catch 返回的值不能是 promise 本身,否则会造成死循环。

async、await

如果 Promise 的回调中出现嵌套,依旧会出现回调地狱;而如今,async await 出现了,它提供了一种新的编写异步代码方式,使得异步代码看起来像是同步代码。

async

异步函数声明很简单,但调用异步函数时它自动返回的是一个Promise对象

async function show() {
    return 'getshow';
}
show().then((data) => {
    console.log(data);
})

await

await 操作符用于等待一个 Promise 返回结果或者某个直接的值,且 await 必须在异步函数 (async function) 上下文中使用。功能很明确在碰到await一个promise时,暂停等待Promise返回值然后函数在往下进行。

let promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log('执行完成');
        resolve('接收成功执行');
    }, 1000);
})
async function show() {
    let test = await promise;
    return test;
}
show().then((data) => {
    console.log(data);
})

总结

小编这边主要是总结了一下Promise概念以及用法,也简单的总结了一下async,await用法,手写部分功能是不够完善的,只是自己以类方法感受一下内部流程,下一篇文章小编总结复习一下Service Worker / PWA