Promise 作为js中异步操作的重要方法,来解读一下promise的用法

首先promise是一个构造函数,接受一个函数作为参数,而这个函数又包括两个函数形式的参数,resolve和reject,最终返回一个promise对象,当新建一个promise对象的时候,就会自动开始异步操作,所以经常是将promise的创建包括到一个函数中,通过调用函数,完成异步操作。

一个Promise可能的状态有三种,pending,fulfilled,rejected,并且一个promise对象只能从pending状态切换到另外两种状态一次,状态不能发生二次的变化。

resolve函数代表着将promise对象从pending状态改为fulfilled状态,而reject函数代表改为rejected

构造函数返回的promise对象两种使用方法

promise返回的对象叫p

1.then
可以用p.then()里使用两个函数分别作为p1进入fulfilled状态和p1进入rejected状态的执行函数,而在promise构造函数中resolve和reject中获得的参数也可以通过在then中的函数中得到使用

    var p = new Promise(function(resolve, reject){
        //做一些异步操作
        setTimeout(function(){
            console.log('执行完成');
            resolve('随便什么数据');
        }, 2000);
    });
    return p;            
}
runAsync()
runAsync().then(function(data){
    console.log(data);
    //后面可以用传过来的数据做些其他操作
    //......
});

在第一段代码中的随便什么数据这个参数就通过第二段代码中的data参数被异步函数的执行函数得到了,并可以进行响应的操作

2.p1还有catch方法可以使用,使用方法和then的第二个参数是一样的

promise的链式调用

来补充一下promise的链式调用,promise目前比较大的优势就是简化了回调地狱,改善了代码质量和代码可读性,但是promise是如何解决回调地狱的,回调地狱又是什么?

回调地狱:指回调函数中嵌套回调函数,这样的代码可读性比较差,不好维护,而使用promise能改良这一点

function getP1() {
    console.log('getP1开始调用');
    return new Promise((resolve, reject) =>{
        setTimeout(function(){
            console.log('getP1调用完成');
            resolve('getP1调用成功');
        }, 1000);
    });
}

function getP2() {
    console.log('getP2开始调用'); 
    return new Promise((resolve, reject) => {
        setTimeout(function(){
            console.log('getP2调用完成');
            resolve('getP2调用成功');
        }, 2000);
    });
}

function getP3() {
    console.log('getP3开始调用');
    return new Promise((resolve, reject) => {
        setTimeout(function(){
            console.log('getP3调用完成');
            resolve('getP3调用成功');
        }, 3000);
    });
}
getP1()
    .then(res1 => {
        console.log('getP1结果:' + res1) 
        return getP2()
    })
    .then(res2 => {
        console.log('getP2结果:' + res2) 
        return getP3()
    })
    .then(res3 => {
        console.log('getP3结果:' + res3)
    })

then函数会自动返回一个promise函数,而这个promise的状态:

  • 如果then()方法中返回了一个参数值,那么返回的Promise将会变成接收状态。
  • 如果then()方法中抛出了一个异常,那么返回的Promise将会变成拒绝状态。
  • 如果then()方法调用resolve()方法,那么返回的Promise将会变成接收状态。
  • 如果then()方法调用reject()方法,那么返回的Promise将会变成拒绝状态。
  • 如果then()方法返回了一个未知状态(pending)的Promise新实例,那么返回的新Promise就是未知状态。

所以这个函数写法就比较明了,省去了以往使用if else判断的复杂

async和await的用法

async定义异步函数,并要求这个函数如果有返回值必须是一个promise,而在async函数中可以使用await放置在内部promise函数之前,用来等待这个promise的resolve函数的参数,而函数的执行也会在这一行上停止,直到有返回值后再继续执行,将异步操作转化为了和同步操作类似的情况。

值得注意的是,await只能接受promise进入fulfilled状态后的情况,而如果promise进入rejected状态,则会抛出错误,所以一般可以用try/catch包裹await语句,防止抛出错误

我认为async与await最大的作用就是将异步操作的写法与同步操作靠近,方便了代码的写作,也方便在多重异步操作时看出逻辑的变化,增加了代码的可读性

Promise.all()

接受多个promise,全部是fulfilled才调用success1

Promise.all([promise1, promise2]).then(success1, fail1)

Promise.race()

接受多个promise,以最快返回结果的promise决定执行的函数

Promise.race([promise1, promise2]).then(success1, fail1)