萌新前端面试:回调函数和Promise对象

241 阅读2分钟

前言

学前端基础的时候不太理解promise怎么解决回调函数,懂了之后需要知识输出,这不来了。

开始举例

举个例子,室友今天下午5点回来,紧接着吃晚饭30min,洗澡10min,洗衣服20min,零零碎碎的弄完之后看剧,话不多说,用代码来实现

// 吃饭操作时间
function getDinner(fn){
    setTimeout(() => {
        fn("吃晚饭")
    }, 3000);
}
function getBath(fn){
    setTimeout(() => {
        fn("洗澡")
    }, 1000);
}
function getWash(fn){
    setTimeout(() => {
        fn("洗衣服")
    }, 2000);
}
function getTV(fn){
    setTimeout(() => {
        fn("看剧")
    }, 4000);
}

// 执行
getDinner((data)=>{
    console.log(data);
})
getBath((data)=>{
    console.log(data);
})
getWash((data)=>{
    console.log(data);
})
getTV((data)=>{
    console.log(data);
})

按这种同步代码来实现,它是按执行时间快慢来操作,并且也没有达到我们想要的操作

将执行操作使用es5的回调函数稍作修改

// 执行
getDinner((data)=>{
    console.log(data);
    getBath((data)=>{
        console.log(data);
        getWash((data)=>{
            console.log(data);
            getTV((data)=>{
                console.log(data);
            })
        })
    })
})

这样就顺理成章地形成了既在意料之中又在情理之外的——回调地狱

解决方式

解决回调函数产生的代码嵌套问题:
Ⅰ. promise
Ⅱ. async-await
Ⅲ. async.js库【无】

听我一个一个细细道来

Ⅰ.Promise

// 吃饭操作时间
function getDinner(){
    return new Promise((resolve)=>{
        setTimeout(() => {
            resolve("吃晚饭")
        }, 3000);
    })
}
function getBath(){
    return new Promise((resolve)=>{
        setTimeout(() => {
            resolve("洗澡")
        }, 1000);
    })
}
function getWash(){
    return new Promise((resolve)=>{
        setTimeout(() => {
            resolve("洗衣服")
        }, 2000);
    })
}
function getTV(){
    return new Promise((resolve)=>{
        setTimeout(() => {
            resolve("看剧")
        }, 4000);
    })
}

// 执行操作
getDinner().then((data)=>{
    console.log(data);
    return getBath()
}).then((data)=>{
    console.log(data);
    return getWash()
}).then((data)=>{
    console.log(data);
    return getTV()
}).then((data)=>{
    console.log(data);
})

总结一下promise知识点

  • new一下promise的构造函数,分别异步传入调用成功resolve、失败reject的回调函数
  • promise规范then方法可以链式调用
  • 从表面上看,Promise只是能够简化层层回调的写法,而实质上,Promise的精髓是“状态”,用维护状态、传递状态的方式来使得回调函数能够及时调用,它比传递callback函数要简单、灵活的多

Ⅱ.async-await

// 吃饭操作时间
function getDinner(){
    return new Promise((resolve)=>{
        setTimeout(() => {
            resolve("吃晚饭")
        }, 3000);
    })
}
function getBath(){
    return new Promise((resolve)=>{
        setTimeout(() => {
            resolve("洗澡")
        }, 1000);
    })
}
function getWash(){
    return new Promise((resolve)=>{
        setTimeout(() => {
            resolve("洗衣服")
        }, 2000);
    })
}
function getTV(){
    return new Promise((resolve)=>{
        setTimeout(() => {
            resolve("看剧")
        }, 4000);
    })
}

// async函数
async function getData() {
    // 直接获取resolve传递出来的异步数据
    // 里面书写同步代码
    let dinner = await getDinner();
    console.log(dinner);
    let bath = await getBath();
    console.log(bath);
    let wash = await getWash();
    console.log(wash);
    let tv = await getTV();
    console.log(tv);
}
// 调用执行
getData()

总结一下async-await的知识点

  • await只能在async函数中使用,不然会报错
  • await后面最好是接Promise,虽然接其他值也能达到排队效果
  • async函数返回的是一个Promise对象,有无值看有无return值
  • async/await作用是用同步方式,执行异步操作

总结

既然选择了javascript,就要珍惜和它相伴的日子