Promise之深度解析


Promise对象: 它最大的作用就是解决了异步回调函数层层嵌套的问题。
//传统写法:
step1(function (value1) { 
  step2(value1, function(value2) { 
    step3(value2, function(value3) { 
      step4(value3, function(value4) { // ... });
     }); 
  });
});

//Promises的写法:
(new Promise(step1))
  .then(step2)
  .then(step3)
  .then(step4);

从上面代码可以看到,采用Promises接口后,程序变得非常清楚易读

什么是Promise:

promise对象,说白了,就是个代理,充当异步操作与回调函数之间的中介。简单的说就是:每一个异步任务会立刻返回一个Promise对象。Promises对象有一个then方法,允许指定回调函数,在异步任务完成后调用。

Promise接口:

Promise对象有三种状态:
1 异步操作"未完成"(pending)
2 异步操作"已完成" (resolved)
3 异步操作"失败" (rejected)

这三种状态的变化途径只有2种:
1 异步操作从"未完成"到"已完成"
2 异步操作从"未完成“到"失败"

所以Promise对象的最终结果只有两种:
1 异步操作成功 Promise对象传回一个值,状态变为resolved
2 异步操作失败 Promise对象抛出一个错误,状态变为rejected

Promise对象的生成

ES6提供了原生的Promise构造函数

var promise = new Promise(function (resolve, reject) {
  if(/*异步操作成功*/){
    resolve(value)
  }else {
    reject(error);
  }
});

Promise构造函数接收一个函数作为参数(必须),该函数的两个参数分别是resolve和reject.它们是两个函数。 resolve函数的作用是,将Promise对象的状态从"未完成"变成"成功",并将异步操作的结果,作为参数传递出去。reject函数的作用是,将Promise对象的状态从"未完成"变成"失败",在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。Promise实例生成后,你可以在你想用的地方去调用then方法

Promise的方法

API-1: Promise.all(iterable)
Promise.all(iterable)方法会等iterable参数内的所有promise都被resolve后resolve, 或以第一个promise被reject的原因而reject。

API-2:Promise.race(iterable)
Promise.race(iterable)方法返回一个promise,这个promise在iterable中任意一个promise被解决或拒绝后,立刻以相同的解决值被解决或以相同的拒绝原因被拒绝

Promise的应用

先来看看Promise的兼容性:

Paste_Image.png

如何做到兼容:
方法一:通过Polyfill 类库
jakearchibald/es6-promise:一个兼容 ES6 Promises 的Polyfill类库。 它基于 RSVP.js 这个兼容 Promises/A+ 的类库, 它只是 RSVP.js 的一个子集,只实现了Promises 规定的 API。
yahoo/ypromise: 这是一个独立版本的 YUI 的 Promise Polyfill,具有和 ES6 Promises 的兼容性。
getify/native-promise-only: 以作为ES6 Promises的polyfill为目的的类库 它严格按照ES6 Promises的规范设计,没有添加在规范中没有定义的功能。 如果运行环境有原生的Promise支持的话,则优先使用原生的Promise支持。
方法二:通过扩展类库
then/promise: a super set of ES6 Promises designed to have readable, performant code and to provide just the extensions that are absolutely necessary for using promises today.
petkaantonov/bluebird: 这个类库除了兼容 Promise 规范之外,还扩展了取消promise对象的运行,取得promise的运行进度,以及错误处理的扩展检测等非常丰富的功能,此外它在实现上还在性能问题下了很大的功夫。
when: 大小很小,node和浏览器环境下都可以使用。
q: 类库 Q 实现了 Promises 和 Deferreds 等规范。 它自2009年开始开发,还提供了面向Node.js的文件IO API Q-IO 等, 是一个在很多场景下都能用得到的类库。

接下来看两个简单的应用:
应用一:加载图片
我们可以把图片的加载写成一个Promise对象

var preloadImage = function (path) { 
  return new Promise(function (resolve, reject) { 
    var image = new Image(); 
    image.onload = resolve; 
    image.onerror = reject; 
    image.src = path; 
  });
};

应用二:Ajax操作

function search(term, onload, onerror) { 
  var xhr, results, url; 
  url = 'http://example.com/search?q=' + term; 

  xhr = new XMLHttpRequest(); 
  xhr.open('GET', url, true); 

  xhr.onload = function (e) { 
    if (this.status === 200) { 
      results = JSON.parse(this.responseText); 
      onload(results);
     } 
  }; 
  xhr.onerror = function (e){
    onerror(e);
  };
  xhr.send();
}
search("Hello World", console.log, console.error);

改写后

function search(term, onload, onerror) { 
  var url = 'http://example.com/search?q=' + term;
  var xhr = new XMLHttpRequest(); 
  var result;

  var p = new Promise(function (resolve, reject) {
    xhr = new XMLHttpRequest(); 
    xhr.open('GET', url, true); 

    xhr.onload = function (e) { 
       xhr.open('GET', url, true);
       xhr.onload = function (e) {
         if (this.status === 200) { 
            results = JSON.parse(this.responseText); 
            resolve(results);
        }; 
      } 
      xhr.onerror = function (e){
        reject(e);
      };
      xhr.send();
   });
   return p;
}
search("Hello World", console.log, console.error);
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容