JavaScript中Promises/A+规范的实现

Promises是一种异步编程模型,通过一组API来规范化异步操作,这样也能够让异步操作的流程控制更加容易。

下面的代码是假设执行一个异步队列,每一项都会使用上一项返回的数据:

function nest(url, params, fn) {
    $.getJSON(url, params, function(data) {
        console.log(data);
        fn.call(this);
    });
}
nest(‘promise.php‘, {a:1}, function(data1) {
    nest(‘promise.php‘, {b:2}, function(data2) {
        nest(‘promise.php‘, {c:3}, function(data3) {
            console.log(‘同步完成‘);
        });
    });
});

这是一个回调金字塔,当异步的任务很多的时候,需要维护大量的callback。这嵌套的自己眼睛都看不清了吧。

Promise/A+规范就是为了解决上面的问题,可以用类似下面的代码来改进,“nest”也会做些修改:

promise.then(nest(‘promise.php‘, {a:1}))
    .then(nest(‘promise.php‘, {b:2}))
    .then(nest(‘promise.php‘, {c:3}));

下图是改进的图片示例,我在画图的时候也感觉到,左边的比较难画,右边的很好画。

接下来会围绕改进金字塔,实现规范展开。

一、Promises/A+规范说明

Promises/A+规范如下:

1)一个promise可能有三种状态:等待(pending)、已完成(fulfilled)、已拒绝(rejected)

2)一个promise的状态只可能从“等待”转到“完成”态或者“拒绝”态,不能逆向转换,同时“完成”态和“拒绝”态不能相互转换

3)promise必须实现then方法,而且then必须返回一个promise

4)同一个promise的then可以调用多次,并且回调的执行顺序跟它们被定义时的顺序一致

5)then方法接受两个参数,第一个参数是成功时的回调,在promise由“等待”态转换到“完成”态时调用

6)另一个是失败时的回调,在promise由“等待”态转换到“拒绝”态时调用。

7)then可以接受另一个promise传入,也接受一个“类then”的对象或方法,即thenable对象。

接下来先实现一个简易的,只有完成状态,没有拒绝和等待状态。

二、简单实现

Promise对象的实现:

function Promise(fn) {
  this._status = ‘pending‘;
  this._resolves = []; //队列
  this._fn = fn;
  return this;
}
Promise.prototype = {
  then: function(resolve) {
    var next = this._next || (this._next = new Promise()); //下一个promise对象
    this._resolves.push(resolve); //设置队列
    return next;
  },
  resolved: function(value) { //改变状态
    this._status = ‘fulfilled‘;
    this._result = (this._fn && this._fn(value)) || value;
    while (fn = this._resolves.shift()) { //循环调用队列
      this._fire(this._next, fn);
    }
  },
  _fire: function(nextPromise, nextFn) {
    var nextResult = nextFn(this._result);
    if (nextResult instanceof Promise) { //判断回调是否是Promise对象
      //只有当nextResult的状态为fulfilled,下一个promise才可以执行
      nextResult.then(function(value) {
        nextPromise.resolved(value);
      });
    } else {
      nextPromise.resolved(nextResult);
    }
  }
};

演示用的函数:

function nest2(url, params) {
  return function(pre) {
    var promise = new Promise();
    $.getJSON(url, params, function(data) {
      promise.resolved(data);
    });
    return promise;
  };
}

function begin(value) {
  return value + ‘!‘;
}

初始化代码:

var promise = new Promise(begin);
promise.then(nest2(‘promise.php‘, {a: 1}))
  .then(nest2(‘promise.php‘, {b: 2}));
promise.resolved(‘开始‘);

也可以另外一种方式调用,这样的话内部的_resloves队列中会有多个值

var promise = new Promise(begin);promise.then(nest2(‘promise.php‘, {a: 1}))
promise.then(nest2(‘promise.php‘, {b: 2}));
promise.resolved(‘开始‘);

demo下载:

http://download.csdn.net/detail/loneleaf1/9391315

参考资料:

http://www.alloyteam.com/2014/05/javascript-promise-mode/   JavaScript Promise启示录

http://www.cnblogs.com/fsjohnhuang/p/4135149.html   JS魔法堂:剖析源码理解Promises/A规范

http://www.cnblogs.com/aaronjs/archive/2012/11/17/2774440.html   使用Promises/A

http://rapheal.sinaapp.com/2013/01/26/jquery-src-deferred/   $.Deferred

http://www.ituring.com.cn/article/66566   Promises/A+规范

时间: 2024-12-26 12:37:20

JavaScript中Promises/A+规范的实现的相关文章

辛星浅析JavaScript中的编程规范

这是接着上一篇的博文写的,首先说一下编程规范的重要性吧,它可以让我们的代码保持一致性,可预测,更易于阅读和理解.一个新的开发者可以通过阅读规范,理解其他团队成员书写的代码,更快的上手干活. 第一点就是缩进. 很糟糕的一件事就是不一致的缩进,因为它看上去像是遵循了规范,但是可能一路上伴随着混乱和惊奇,重要的是规范的使用缩进. 一些开发人员喜欢用tab制表符缩进,因为任何人都可以调整他们的编辑器以自己喜欢的空格数来显示tab.也有人喜欢用空格,通常是四个空格.一般这个无所谓,只要团队每个人都遵循同一

JavaScript中模块“写法”

在JavaScript模块到底是什么 event = function() { // do more return { bind: function() {}, unbind: function() {}, trigger: function() {} }; }();这能代表"模块"吗?这就是一个JS对象啊,以为有多么深奥. 是的,JavaScript中模块多数时候被实现为一个对象.这么看来,多数时候我们都写过"模块"(但没有在整个项目中应用模块化思想).或许每个人

通过一道笔试题浅谈javascript中的promise对象

因为前几天做了一个promise对象捕获错误的面试题目,所以这几天又重温了一下promise对象.现在借这道题来分享下一些很基础的知识点. 下面是一个面试题目,三个promise对象捕获错误的例子,返回结果有什么不同. //使用throw添加错误事件 var p = new Promise(function(resolve, reject) { resolve("ok"); throw new Error('error0'); //setTimeout(function() { thr

对 Promises/A+ 规范的研究 ------引用

作为 Modern JavaScript 基础设施的一部分,Promises 对前端开发者而言异常重要.它是 async/await 语法的基础,是 JavaScript 中处理异步的标准形式.并且,未来的 Web API,只要是异步的,都会以 Promises 的形式出现. 1.实现 Promises/A+ 规范 1.1.前期工作 An open standard for sound, interoperable JavaScript promises https://promisesaplu

Promises/A+规范

为什么需要异步编程方式 一个函数执行之后,在它后面顺序编写的代码中,如果能够直接使用它的返回结果或者它修改之后的引用参数,那么我们通常认为该函数是同步的. 如果一个函数的执行结果或者其修改的引用参数,需要通过设置回调函数或者回调事件的方式来获取,而在其后顺序编写的代码中无法直接获取的话,那么我们通常认为这样的函数是异步的. 阻塞带来的问题是当前线程(或进程)会陷入等待,一直等到阻塞结束,这样就会造成线程(或进程)资源的浪费.所以通常认为阻塞是不够高效的. 如果要编写非阻塞代码,使用同步方式会变得

URL地址中中文乱码详解(javascript中encodeURI和decodeURI方法、java.net.URLDecoder.encode、java.net.URLDecoder.decode)

引言: 在Restful类的服务设计中,经常会碰到需要在URL地址中使用中文作为的参数的情况,这种情况下,一般都需要正确的设置和编码中文字符信息.乱码问题就此产生了,该如何解决呢?且听本文详细道来. 1.  问题的引出 在Restful的服务设计中,查询某些信息的时候,一般的URL地址设计为: get /basic/service? keyword=历史 , 之类的URL地址. 但是,在实际的开发和使用中,确是有乱码情况的发生,在后台的读取keyword信息为乱码,无法正确读取. 2. 乱码是如

[译]JavaScript中,{}+{}等于多少?

[译]JavaScript中,{}+{}等于多少? 原文:http://www.2ality.com/2012/01/object-plus-object.html 最近,Gary Bernhardt在一个简短的演讲视频“Wat”中指出了一个有趣的JavaScript怪癖:在把对象和数组混合相加时,会得到一些你意想不到的结果.本篇文章会依次讲解这些计算结果是如何得出的. 在JavaScript中,加法的规则其实很简单,只有两种情况:你只能把数字和数字相加,或者字符串和字符串相加,所有其他类型的值

C++、Java、JavaScript中的异常处理(Exception)

编程思想之异常处理 什么叫异常处理? 什么叫异常(Exception)?顾名思义就是非正常的情况,出现了不希望出现的意外,异常处理就是遇到这种意外时准备的对策和解决方案.比如您开着一辆劳斯莱斯在公路上行走,突然前面出现一个小孩,幸好您眼疾手快紧急刹车,而避免了一场交通事故.在这个例子中突然出现的小孩就是异常,紧急刹车就是异常处理(面对这种突发情况采取的解决方案). 程序来源于现实,是现实的抽象和模拟,也会有异常,因此异常的处理就显示的极为重要.试想如果您的手机的某个应用使用两下就崩溃了,或都出现

JavaScript中声明是否有var的区别

本文来论述JavaScript中变量声明有var和没有var的区别,关于JavaScript中的变量声明的作用域是以函数为单位,所以我们经常见到避免全局变量污染的方法是: (function(){ // ... })(); 在函数内部,有var和没var声明的变量是不一样的.有var声明的是局部变量,没var的,声明的全局变量,所以可以借此向外暴露接口东东. 在全局作用域内声明变量时,有var 和没var看起来都一样,我们知道,声明的全局变量,就是window的属性,究竟是否一样,我们通过ECM