Promise由浅入深

931 阅读4分钟

1、Promise的由来、

在Promise出现以前,处理一个异步网络请求,大概如下

// 请求 代表 一个异步网络调用。
// 请求结果 代表网络请求的响应。
请求1(function(请求结果1){
    处理请求结果1
})

乍一看,好像没什么问题,但现在需求变了,需要在第一个请求的基础上,去执行第二个网络请求,代码如下。

请求1(function(请求结果1){
    请求2(function(请求结果2){
        处理请求结果2
    })
})

再一看,好像也还行吧,但是,请看下面。

请求1(function(请求结果1){
    请求2(function(请求结果2){
        请求3(function(请求结果3){
            请求4(function(请求结果4){
                请求5(function(请求结果5){
                    请求6(function(请求结果3){
                        ...
                    })
                })
            })
        })
    })
})

看起来是不是很熟悉,没错,这就是回调地狱了。 回调地狱代码臃肿、不易维护、复用性差、容易滋生bug。 总之,这样的代码,对人类非常不友好!!!

所以呢,针对这个异步嵌套的问题,就有人想出了能友好解决的方法,Promise就是这样诞生了。

2、什么是Promise?

Promise是一种异步编程的解决方案,比传统的异步解决方案【回调函数】和【事件】更合理、更强大,并且被列入了ES6规范中。

2.1 Promise常用写法

new Promise(请求1)
    .then(请求2(请求结果1))
    .then(请求3(请求结果2))
    .then(请求4(请求结果3))
    .then(请求5(请求结果4))
    .catch(处理异常(异常信息))

与上面的回调函数的写法相比,Promise更为直观、更人性化,并且能够在外层函数捕获异步函数的异常信息。

2.2 常用API

首先要new一个Promise对象。

const p1 = new Promise((resolve,reject) => {
    if(success){
        resolve(value);//将状态改为成功
    }else{
        reject(value);//将状态改为失败
    }
})

1、接着调用Promise对象上的方法,then

p1.then((value) => {
    成功的回调
},(error) => {
    失败的回调
}
)

then就是为Promise注册回调函数

(1)从中可以看出,then函数接受两个参数,两个参数为函数。第一个参数是,状态为resolve状态下的回调函数;第二个参数是,状态为reject状态下的回调函数。第二个参数不是必传的。

(2)then里面的方法,只有在Promise对象的状态为resolve或者reject才会被执行,并且接收resolve(value)的value作为参数

2、接着调用Promise对象上的方法,catch

p1
    .then((value) => {
        success
    })
    .catch((error) => {
        error
    })

catch就是捕获异常信息的

3、接着调用Promise对象上的方法,race

多个Promise任务同时执行,返回最先结束的Promise任务的结果,不论是成功还是失败。 简单来说,就是先到先得,近水楼台先得月。

4、接着调用Promise对象上的方法,all

多个Promise任务一起执行,如果全部成功,则返回一个新的Promise对象。 如果有一个为失败,则返回失败的Promise对象。

以上就是一些常用的API了,掌握了这几个APi也基本够用了!)

2.3 实例理解Promise

为了更好地理解Promise,这里我借用一个现实生活的例子,原文。 我们可以把 Promise 比作一个保姆,家里的一连串的事情,你只需要吩咐给他,他就能帮你做,你就可以去做其他事情了。

比如,作为一家之主的我,某一天要出门办事,但是我还要买菜做饭送到老婆单位(请理解我在家里的地位。。) 出门办的事情很重要,买菜做饭也重要。 。但我自己只能做一件事。 这时我就可以把买菜做饭的事情交给保姆,我会告诉她:

  • 你先去超市买菜。
  • 用超市买回来的菜做饭。
  • 将做好的饭菜送到老婆单位。
  • 送到单位后打电话告诉我。

上面前三个步骤是需要消耗时间的,可以看做是异步任务,用Promise的写法如下。

function 买菜(resolve,reject) {
    setTimeout(function(){
        resolve(['西红柿''鸡蛋''油菜']);
    },3000)
}
function 做饭(resolve, reject){
    setTimeout(function(){
        //对做好的饭进行下一步处理。
        resolve ({
            主食: '米饭',
            菜: ['西红柿炒鸡蛋''清炒油菜']
        })
    },3000) 
}
function 送饭(resolve,reject){
    //对送饭的结果进行下一步处理
    resolve('老婆的么么哒');
}
function 电话通知我(){
    //电话通知我后的下一步处理
    给保姆加100块钱奖金;
}

现在有四个任务,需要告诉保姆任务的步骤,在Promise中就是实例Promise对象,用then注册回调函数,按时间顺序执行任务列表中的任务。

// 告诉保姆帮我做几件连贯的事情,先去超市买菜
new Promise(买菜)
//用买好的菜做饭
.then((买好的菜)=>{
    return new Promise(做饭);
})
//把做好的饭送到老婆公司
.then((做好的饭)=>{
    return new Promise(送饭);
})
//送完饭后打电话通知我
.then((送饭结果)=>{
    电话通知我();
})

怎么样,这个例子,是不是让人茅塞顿开,瞬间觉得Promise是如此简单!)