概述

为了体验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对象。

本篇博文实现功能2:多异步情形。

多异步情形

在多异步情形下,成功回调和失败回调的处理方式有如下情况:

  1. 成功回调接收所有参数,失败回调接收单一参数,只要失败,成功回调不执行,只执行相应失败回调。
  2. 成功回调接收所有参数,失败回调接收单一参数,就算失败,也执行成功回调。
  3. 成功回调接收所有参数,失败回调接收所有参数,就算失败,也执行成功回调。
  4. 等等。

上面的情况都可以实现,但是只有情况1比较符合实际业务,所以我们只实现情况1.

实现的方法是:我们引入一个哨兵变量,并且把返回的数据按顺序储存起来,用哨兵变量判断出最后一个成功返回后,表示数据全部返回,然后执行回调函数。

代码如下:

// 模拟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);
}
});
} let Promise = function() {
this.eventName = {
success: [],
error: []
};
// 返回数据的结果集合
this.result = [];
// 哨兵变量
this.sum = 0;
this.count = 0;
}; 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 index = this.sum;
this.sum ++;
setTimeout(() => {
let that = this;
mockAjax({
url: url,
type: 'get',
success: function (data, status) {
if(that.sum !== 0) {
that.result[index] = data;
that.count ++;
if(that.count == that.sum) {
let successList = that.eventName.success;
if(successList || successList.length) {
for(let i = 0; i < successList.length; i++) {
successList[i](that.result, status);
}
}
// 初始化
that.result.length = 0;
that.sum = 0;
that.count = 0;
}
}
},
error: function (err, status) {
that.result.length = 0;
that.sum = 0;
that.count = 0;
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) => (result, status) => {
result.map(ele => {
console.log(ele + '成功回调' + 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)).get('url2').success(successCallback(3)).error(errorCallback(3)).get('url3');

测试输出结果如下:

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

可以看到,成功情况,对返回的三个数据依次执行成功123;失败情况,只对失败的url1执行了失败回调123。

把ajax包装成promise的形式(3)的更多相关文章

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

    概述 为了体验promise的原理,我打算自己把ajax包装成promise的形式.主要希望实现下列功能: // 1.使用success和error进行链式调用,并且可以在后面加上无限个 promis ...

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

    概述 为了体验promise的原理,我打算自己把ajax包装成promise的形式.主要希望实现下列功能: // 1.使用success和error进行链式调用,并且可以在后面加上无限个 promis ...

  3. 如何把 Callback 接口包装成 Promise 接口

    最近一段时间一直在看Node.js,在开发过程中经常要调用一些异步接口,通常在接口的最后一个参数会传入一个回调函数,可以用来处理异常,非异常情况.大致模式如下: var fs = require(“f ...

  4. Finder Item脚本如何包装成 Mac App

    第一步,包装 记得之前把一个 java 程序的 jar 包 用 automator包装成了 app, 但自己找不到做法了.回头我想了想 这么实验可行. 这样做成 app 后保存在 /Applicati ...

  5. (转)Groupon前传:从10个月的失败作品修改,1个月找到成功 并不挶泥在这个点子上面,它反而往后站一步,看看他们已经做好的这个网站,可以再怎么包装成另一个完完全全不同的网站?所有的人所做的每件失败的事情中, 一定有碰到或含有成功的答案」在里面,只是他们不知道而已。 人不怕失败」,只怕宣布失败」

    (转)Groupon前传:从10个月的失败作品修改,1个月找到成功 今天读到 一个非常励志人心的故事 ,就像现在「叶问」有「前传」,最近很火红的团集购网站Groupon 也出现了「Groupon前传」 ...

  6. SIP:用Riverbank的SIP创建C++库的Python模块(把自己的C++库包装成Python模块)

    我们发现PyQt做的Python版的PyQt是如此好用,如果想把自己的C++库包装成Python模块该如何实现呢? 这里介绍下用SIP包装C++库时值得参考的功能实现: 需要Python模块中实现C+ ...

  7. [Python] 将视频转成ASCII符号形式、生成GIF图片

    一.简要说明 简述:本文主要展示将视频转成ASCII符号形式展示出来,带音频. 运行环境:Win10/Python3.5. 主要模块: PIL.numpy.shutil. [PIL]: 图像处理 [n ...

  8. 安卓、ios时间转换成时间戳的形式

    将日期转换成时间戳的形式,在安卓和ios不同的系统下转正会有兼容性的问题 安卓系统下Date.parse(new Date('2018-03-30 12:00:00'))会直接转换成时间戳的形式(简单 ...

  9. Oracle中使用Table()函数解决For循环中不写成 in (l_idlist)形式的问题

    转: Oracle中使用Table()函数解决For循环中不写成 in (l_idlist)形式的问题 在实际PL/SQL编程中,我们要对动态取出来的一组数据,进行For循环处理,其基本程序逻辑为: ...

随机推荐

  1. 修改Myeclipse的文件默认为UTF-8编码

    一.工程编码默认调整 windows->Preferences...打开"首选项"对话框, 左侧导航树,导航到general->Workspace,右侧 Text fi ...

  2. 自定义View之一圆形图片

    自定义View的方法 对现有控件进行扩展 通过组合来实现新的控件 重写View来实现全新的控件 本篇文章主要讲对现有控件的扩展 1.圆形图片控件 自定义View,对ImageView的扩展 重写onD ...

  3. 内嵌圆角CSS实现

    前言 开发项目时,经常会遇到如上图左上角和右上角这种内嵌的圆角效果,在以前css3还没有普及时不用说一张图片搞定,但是到现在我们完全可以用css去实现. 实现 第一步:思路 仔细观察这个小缺角,它其实 ...

  4. function 函数

    function:函数体内部的语句在执行时,一旦执行到return时,函数就执行完毕,并将结果返回.因此,函数内部通过条件判断和循环可以实现非常复杂的逻辑. 如果没有return语句,函数执行完毕后也 ...

  5. Git push 提交代码到远程global user.name错误解决办法

    问题:安装了Git-1.9.4-preview和TortoiseGit等工具后,Git服务器开通了账号和密码并配置了邮箱.克隆了服务器代码到本地,按需求进行代码开发.提交本地代码到服务器时出现错误.具 ...

  6. jieba库词频统计

    一.jieba 库简介 (1) jieba 库的分词原理是利用一个中文词库,将待分词的内容与分词词库进行比对,通过图结构和动态规划方法找到最大概率的词组:除此之外,jieba 库还提供了增加自定义中文 ...

  7. HCNA之网络通信基础

    一.通信与网络 通信的概念我们并不陌生,在人类社会的起源和发展过程中,通信就直伴随着我们.般认为, 20世纪七.八十年代,人类社会已进入到信息时代,对于生活在信息时代的我们,通信的必要性和重要性更是不 ...

  8. 【翻译】Flume 1.8.0 User Guide(用户指南) Sink

    翻译自官网flume1.8用户指南,原文地址:Flume 1.8.0 User Guide 篇幅限制,分为以下5篇: [翻译]Flume 1.8.0 User Guide(用户指南) [翻译]Flum ...

  9. php7 三元运算 精简

    $abc = isset($_GET['name'])?$_GET['name']:'abc'; // 5.+ $abcd = $_GET[

  10. metasploit生成payload的格式

    转自https://www.cnblogs.com/zlgxzswjy/p/6881904.html Often one of the most useful (and to the beginner ...