为了账号安全,请及时绑定邮箱和手机立即绑定

我的前端进阶学习(二)—— promise

标签:
JavaScript

本文是我在学习一个开源的 Ajax 库时所总结的内容,总共分为了几个部分
这是其中第二部分,关于 Promise

引言

随着技术的发展,我们在编写的前端程序越来越复杂,其中有一个就是对异步任务的处理。我们希望在处理异步调用时需要对两种结果进行操作——成功操作和失败处理。再成功调用后,我们还可能将返回的结果用在另一个异步任务中,这样就会出线“函数连环嵌套”的情况。可以看看下面的示例代码:

function getSometing(data, onload, onerror) {
    var xhr, results, url;
    url = 'url' + data;
    xhr = new XMLHttpRequest();
    xhr.open('GET', url, true);

    xhr.onload = function () {
        // 成功回调函数
        if (this.status === 200) {
            results = JSON.parse(this.responseText);
            onload(results);
        }
    };

    xhr.onerror = function (e) {
        // 失败回调函数
        onerror(e);
    };

    xhr.send();
}

function handleError(error) {}  // 错误处理函数
function handleResult() {}      // 结果处理函数

function doSomething() {
    var container = document.getElementById('container');

    searchTwitter('data1', function (result1) {
        searchTwitter('data2', function (result2) {
            handleResult(result1, result2);
            });
        }, handleError);
    }, handleError);
}

上面的代码是一段典型的处理Ajax的程序,我们可以看到有许多的嵌套的回调函数在其中。这样的代码即不容易理解,看起来也不太美观,同时对错误的处理也变得十分的分散。而我在 Ajax 的源码中,学习到了一种方法正好可以处理这样的问题,这种处理模式称为promise

promise的英文意思有承诺(诺言)的意思,用在这里我们可以简单的理解为:异步函数在处理的过程中返回了代表承诺的promise对象。我们通过在对象上进行操作来完成我们的后续操作。

下面是引用别人对promise的解释:

所谓 Promise,就是一个对象,用来传递异步操作的消息。它代表了某个未来才会知道结果的事件(通常是一个异步操作),并且这个事件提供统一的 API,可供进一步处理。

promise模式在任何时刻都处于以下三种状态之一:未完成(unfulfilled)、已完成(resolved)和拒绝(rejected)。以CommonJS Promise/A 标准为例,promise对象上的then方法负责添加针对已完成和拒绝状态下的处理函数。then方法会返回另一个promise对象,以便于形成promise管道,这种返回promise对象的方式能够支持开发人员把异步操作串联起来,如then(resolvedHandler, rejectedHandler); 。resolvedHandler 回调函数在promise对象进入完成状态时会触发,并传递结果;rejectedHandler函数会在拒绝状态下调用。

如何自己实现一个promise

我的目的不仅仅是简单了解promise,而是自己去实现一个promise

先看看 Ajax 是怎样做的。具体看下面代码的注释。
下面的代码不推荐新手看,真的不推荐

function Ajax(options) {
    options = options || {}

    // 定义对象保存相关内容,这一个值得学习
    var $public = {}
    var $private = {}

    // 定义 promise 需要的几种方法
    $private.methods = {
        then: function () { },
        catch: function () { },
        always: function () { },
    }

    // $public.get() == function(){}  
    // 函数返回一个 Ajax 操作的结果
    $public.get = function (url, data) {
        // 注意这里,这个操作返回的就是我们一个 `promise` 对象
        return $private.xhrConnection(method, url, data, options);
    }

    $private.xhrConnection = function xhrConnection(type, url, data, options) {
        // 通过 readystatechange 事件改变 `promise` 的状态
        xhr.addEventListener('readystatechange', $private.ready, false)
        // 返回 $private.promises 返回值 ==> allPromises
        return $private.promises()
    }

    $private.ready = function ready() {
        var xhr = this
        if (xhr.readyState === xhr.DONE) {
            xhr.removeEventListener('readystatechange', $private.ready, false)
            $private.methods.always
                .apply($private.methods, $private.parseResponse(xhr))
            if (xhr.status >= 200 && xhr.status < 300) {
                // 成功处理函数
                $private.methods.then
                    .apply($private.methods, $private.parseResponse(xhr))
            } else {
                // 失败处理函数
                $private.methods.catch
                    .apply($private.methods, $private.parseResponse(xhr))
            }
        }
    }

    $private.promises = function promises() {
        // 设置对应的回调函数
        var allPromises = {}
        Object.keys($private.methods).forEach(function (method) {
            allPromises[method] = $private.generatePromise.call(this, method)
        }, this)
        return allPromises
    }

    $private.generatePromise = function generatePromise(method) {
        return function (callback) {
            $private.methods[method] = callback
            return this
        }
    }

    return $public
}

自己实现的话可以参考下面的 《JavaScript异步编程的Promise模式》 文章,我这里没有合适的演示代码,以后有的话再补上。

总结

其实promise这个东西我很早前就接触过,但心中一直对不了解的东西有所抵触,导致自己一直都没有真正的去理解这些东西。

但如果一直因为不了解或者觉得这个东西很难,自己不想学的话,那么就永远没有机会去学习它。

扩展阅读
点击查看更多内容
9人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消