callBack ->Promise->async/await

1,079 阅读3分钟

Promise困扰了我很久,最近突然开窍了,于是一鼓作气,总结一下。

Promise是承诺的意思,比如我妈让我现在去拖地,我跟妈妈说,吃完这个苹果就去拖地,那么我承诺我去拖地,但是要在吃完苹果之后;在代码中如何实现呢?

假如今天我们还不知道有promise,那么我们会用回调函数解决,比如

function eatApple(callback){
    setTimeout(function(){
        console.log('5秒后吃完苹果')
        callback()
    },5000)
}
function sweep(){
    console.log('拖地')
}
eatApple(sweep)

但是如果我的承诺是吃完这个苹果再吃完一个梨再吃完一个香蕉再去拖地呢?那么回调函数大约应该这样写:

function eatApple(callback){
    setTimeout(function(){
        console.log('5秒后吃完苹果')
        callback()
    },5000)
}
function eatPear(callback){
    setTimeout(function(){
        console.log('5秒后吃完梨')
        callback()
    },5000)
}
function eatBanana(callback){
    setTimeout(function(){
        console.log('5秒后吃香蕉')
        callback()
    },5000)
}
function sweep(){
    console.log('拖地')
}
eatApple(()=>{
    eatPear(()=>{
        eatBanana(sweep)
    })
})

看看上面的代码,如果我再多吃几样的话,eatApple里面就会一层套一层再套一层再套一层。。。这就是传说中的回调地狱。。。

但是,今天我们知道了promise的存在,让我们先回到吃完苹果就拖地的情景,上代码:

function eatApple(){
    return new Promise((resolve,reject)=>{
        let a = 1;
        setTimeout(()=>{
            if(a == 1){
                resolve(a)
            }else{
                reject(a)
            }
        },5000)
    })
}
function sweep(){
    console.log('拖地')
}
eatApple().then((a)=>{
    console.log('5秒后吃完苹果',a)
    sweep();
}).catch((a)=>{
    console.log('吃苹果时遇到了困难',a)
})

嗯。。。看着比回调的代码多呢。。。别着急,接着往下走,看看多吃几个水果用promise是怎样解决的(理想主义,不考虑吃的过程中有没有遇到困难):

function eatApple(){
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            console.log('5秒后吃完苹果')
            resolve()
        },5000)
    })
}
function eatPear(){
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            console.log('5秒后吃完梨')
            resolve()
        },5000)
    })
}
function eatBanana(){
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            console.log('5秒后吃香蕉')
            resolve()
        },5000)
    })
}
function sweep(){
    console.log('拖地')
}
eatApple().then(()=>{
    eatPear().then(()=>{
        eatBanana().then(()=>{
            sweep()
        })
    })
})

哎呀,吃多了上火,看起来也没比回调函数优雅呀,我开始怀疑promise是否像传说中的那么厉害了,就在这时,我发现了es7的async/await,异步/等待,事不宜迟,让我们从简单的开始

function eatApple(){
    return new Promise((resolve,reject)=>{
        let a = 1;
        setTimeout(()=>{
            if(a == 1){
                console.log('5秒后吃完苹果')
                resolve(a)
            }else{
                reject(a)
            }
        },5000)
    })
}
async function sweep(){
    try{
        console.log('start');
        let a = await eatApple();
        console.log('拖地',a)
    }catch(err){
        console.log('吃苹果时遇到了困难',err)
    }
}
sweep()

看到不同了吗?我们这次直接执行函数sweep,只要拖地的结果,不管中间是不是吃了苹果,那么在看看多吃几个水果的代码长什么样:

function eatApple(){
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            console.log('5秒后吃完苹果')
            resolve()
        },5000)
    })
}
function eatPear(){
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            console.log('5秒后吃完梨')
            resolve()
        },5000)
    })
}
function eatBanana(){
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            console.log('5秒后吃香蕉')
            resolve()
        },5000)
    })
}
async function sweep(){
    await eatApple();
    await eatPear();
    await eatBanana();
    console.log('拖地')
}
sweep()

太棒了!现在不管我要吃多少个水果,都不用嵌套了!async/await果然优雅!

哦!差点忘了,该去拖地了,不然妈妈就要生气啦-_-!