• 把ajax包装成promise的形式(2)


    概述

    为了体验promise的原理,我打算自己把ajax包装成promise的形式。主要希望实现下列功能:

    // 1.使用success和error进行链式调用,并且可以在后面加上无限个
    promise.get(myUrl).success(successCallback1).error(errorCallback1).success(successCallback2).error(errorCallback2).error(errorCallback3).success(successCallback3);
    
    // 2.支持同时调用多个myUrl,这个时候需要最后的http请求返回之后才执行回调。
    promise.get(myUrl1).success(successCallback1).get(myUrl2).error(errorCallback1).get(myUrl3).error(errorCallback2).success(successCallback1);
    
    // 3.支持post和jsonp请求。
    

    对于ajax我选用jq的ajax,但是尽量不使用jq的deferred对象。

    本篇博文实现一个测试用ajax方法

    测试用ajax

    因为用实际ajax接口非常不方便测试,所以我用setTimeout模拟了一个ajax方法进行测试用。

    值得一提的是,如果在node端,建议使用setImmediate代替setTimeout会有更好的性能。目前浏览器端只有IE支持setImmediate。

    // 模拟ajax
    let mockAjax = ({ url, type, success, error }) => {
        let data = url + type, err = url + type, status;
        // 随机执行success或者error
        setTimeout(() => {
            let rand = Math.random() > 0.1;
            if(rand) {
                status = 1;
                if(typeof success == 'function') success(data, status);
            } else {
                status = 0;
                if(typeof error == 'function') error(err, status);
            }
        });
    }
    

    mockAjax随机进行成功或者失败返回,可以更改上面的0.1来调高或者调低相关概率。

    需要说明的是,最好在chrome的开发者工具下运行上面的代码,其它浏览器可能不支持参数解构

    使用mockAjax进行测试

    // 模拟ajax
    let mockAjax = ({ url, type, success, error }) => {
        let data = url + type, err = url + type, status;
        // 随机执行success或者error
        setTimeout(() => {
            let rand = Math.random() > 0.5;
            if(rand) {
                status = 1;
                if(typeof success == 'function') success(data, status);
            } else {
                status = 0;
                if(typeof error == 'function') error(err, status);
            }
        });
    }
    
    let Promise = function() {
        this.eventName = {
            success: [],
            error: []
        };
    };
    
    Promise.prototype.success = function(cb) {
        this.eventName.success.push(cb);
        return this;
    };
    
    Promise.prototype.error = function(cb) {
        this.eventName.error.push(cb);
        return this;
    };
    
    Promise.prototype.get = function(url) {
        let that = this;
        setTimeout(() => {
            mockAjax({
                url: url,
                type: 'get',
                success: function (data, status) {
                    let successList = that.eventName.success;
                    if(successList || successList.length) {
                        for(let i = 0; i < successList.length; i++) {
                            successList[i](data, status);
                        }
                    }
                },
                error: function (err, status) {
                    let errorList = that.eventName.error;
                    if(errorList || errorList.length) {
                        for(let i = 0; i < errorList.length; i++) {
                            errorList[i](err, status);
                        }
                    }
                }
            });
        });
    
        return this;
    };
    
    // test===================
    let successCallback = (message) => (data, status) => {
        console.log(data + '成功回调' + message);
    }
    let errorCallback = (message) => (err, status) => {
        console.log(err + '失败回调' + message);
    }
    
    let testPromise = new Promise();
    testPromise.get('url1').success(successCallback(1)).success(successCallback(2)).error(errorCallback(1)).error(errorCallback(2));
    

    可以看到浏览器输出如下:

    // 成功情况
    url1get成功回调1
    url1get成功回调2
    // 失败情况
    url1get失败回调1
    url1get失败回调2
    

    多异步协作

    多异步情况下会返回什么呢?

    testPromise.get('url1').success(successCallback(1)).success(successCallback(2)).error(errorCallback(1)).error(errorCallback(2)).get('url2').success(successCallback(3)).error(errorCallback(3)).get('url3');
    

    输出如下:

    url1get成功回调1
    url1get成功回调2
    url1get成功回调3
    url2get成功回调1
    url2get成功回调2
    url2get成功回调3
    url3get失败回调1
    url3get失败回调2
    url3get失败回调3
    

    冷静分析,在url1返回的时候,url2和url3没有返回,此时对url1返回的数据执行了三个成功回调。

    但是更多情况下,我们需要url1, url2, url3全部返回之后再执行成功回调或者失败回调。

    这种功能我们将在下篇博文实现。

  • 相关阅读:
    http 事务
    URI、URL、URN
    媒体类型(MIME类型)
    资源
    WEB客户端和服务器
    如何解决新浪微博返回结果中的中文编码问题
    新浪微博 使用OAuth2.0调用API
    新浪微博 授权机制研究
    hmac库 密钥相关的哈希运算消息认证码
    ValueError: Expecting property name: line 1 column 1 (char 1)
  • 原文地址:https://www.cnblogs.com/yangzhou33/p/9976171.html
Copyright © 2020-2023  润新知