NodeiOS Swift && Objective-C

Promise之深度解析

2016-08-25  本文已影响3220人  天外来人

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);
上一篇下一篇

猜你喜欢

热点阅读