异步无处不在:Promise 破除“回调地狱”(三)

300 阅读2分钟

前两篇讨论了异步模式回调函数,结尾谈到了令人头皮发麻的回调地狱。

要想拯救出回调地狱的代码,只有请我们的 Promise 出山了。

拯救头发小斗士,出发!

Promise

图片

Promise 译为承诺、许诺、希望,意思就是异步任务交给我来做,一定(承诺、许诺)给你个结果。

在执行的过程中,Promise 的状态会修改为 pending。一旦有了结果,就会再次更改状态。

异步执行成功的状态是 Fulfilled , 这就是承诺给你的结果。状态修改后,会调用成功的回调函数 onFulfilled 来将异步结果返回。

异步执行成功的状态是 Rejected,这就是承诺给你的结果。然后调用 onRejected 说明失败的原因(异常接管)。

如果将前面对 ajax 函数的封装,改为 Promise 的方式,结果又会是什么?

Promise 重构 Ajax 的异步请求封装

function myAjax(url) {
    return new Promise(function (resolve, reject) {
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function () {
            if (this.readyState == 4) {
                if (this.status == 200) {
                    // 成功的回调
                    resolve(this.responseText)
                } else {
                    // 失败的回调
                    reject(new Error());
                }
            }
        }

        xhr.open('get', url)
        xhr.send();
    })
}

还是前面提到的逻辑,如果返回的结果中,又有 ajax 请求需要发送,可一定记得使用链式调用,不要在 then 中直接发起下一次请求,否则,又是地狱相见了。

//  ==== Promise 误区====
myAjax('./d1.json').then(data=>{
    console.log(data);
    myAjax('./d2.json').then(data=>{
        console.log(data)
        // ……回调地狱……
    })
})

链式的意思就是在上一次 then 中,返回下一次调用的 Promise 对象,我们的代码就不会进地狱了。

myAjax('./d1.json')
    .then(data=>{
    console.log(data);
    return myAjax('./d2.json')
})
    .then(data=>{
    console.log(data)
    return myAjax('./d3.json')
})
    .then(data=>{
    console.log(data);
})
    .catch(err=>{
    console.log(err);
})

终于逃脱了回调地狱!

虽然我们脱离了回调地狱,但是 .then 的链式调用依然不太友好。

频繁的 .then 并不符合自然的运行逻辑,Promise 的写法只是回调函数的改进,使用then 方法以后,异步任务的两段执行看得更清楚了,除此以外,并无新意。

Promise 的最大问题是代码冗余。原来的任务被 Promise 包装了一下,不管什么操作,一眼看去都是一堆 then,原来的语义变得很不清楚。

于是,在 Promise 的基础上,Async 函数出现了。

终极异步解决方案,千呼万唤地在 ES2017 中发布了。

下一篇,展开说说(ง •_•)ง。