ECMAScript 6 Promise对象学习之Promise对象的使用

 2015年07月28日    132     声明


上篇对ECMAScript 6中的Promise对象做了介绍,通过上篇文章对Promise的由来及Promise对象的使用应该能有基本了解。本篇是在上篇基础上的一个延伸,本篇将对Promise对象中的一些概念做进一步的说明。在本文的后半部分,是一个Promise对象的使用示例,结合示例可以对Promise对象有更清晰的了解。

  1. Promise对象相关说明
  2. Promise对象的使用


1. Promise对象相关说明


1.1 全局对象Promise与构造函数Promise

在ECMAScript 6中Promise是一个全局对象,也可以理解为Promise是一个类。而创建Promise对象的实例,要使用Promise对象的构造函数。创建方式为:

var promise = new Promise(function(resolve, reject) {}); 

在上面示例代码中,PromisePromise对象的构造函数,而Promise是通过构造函数创建的对象实例。在这里需要对Promise对象(类)、Promise对象的构造函数、Promise对象实例区分清楚,这就涉及到了面向对象的概念,本站曾整理过一篇JavaScript中实现面向对象思想的文章:JavaScript面向对象:类、方法、属性

在面向对象思想中,类的方法有两种:实例方法、静态方法(也叫:类方法)。两种方法的区别是:实例方法需要创建类实例后才可以调用,其调用格式为:实例名.方法(),在ECMAScript中,实例方法是指定义在prototype原型链上的方法,如:Promise对象的thencatch方法;而静态方法则不需要实例化,其调用格式为:类名.方法(),如:Promise对象的allresolve等方法。


1.2 then方法与catch方法

Promise对象中有两个实例方法:thencatchthen方法可以接受两个回调函数作为参数,这个参数分别用于操作成功和操作失败时的处理。而catch只用于操作失败时的处理。因此,对于一个Promise对象实例,可能就会有以下几种写法:

1. 使用then方法进行正常、异常处理:

promise.then(function(result) {
    // 操作成功
}, function(err) {
    // 操作失败
});

2. 使用then方法进行异常处理:

promise.then(undefined, function(err) {
    // 操作失败
});

3. 使用then方法和catch进行正常、异常处理:

promise.then(function(result) {
    // 操作成功
}).catch(function(err) {
    // 操作失败
});

4. 使用catch方法进行异常处理:

promise.catch(function(err) {
    // 操作失败
});

从上面示例代码可以看出,catch方法其实是then(undefined, onRejected)的方法别名。与使用 .then(onFulfilled, onRejected)这样带有两个参数的调用形式相比,更推荐使用 thencatch 的处理方式,使用then方法处理resolve操作成功的情况和使用catch方法处理reject操作失败的情况,也就是上面第3种情况。


1.3 Promise.resolve方法与thenable对象

一般情况下我们会使用new Promise()来创建Promise对象实例。除使用构造函数外,我们还可以使用Promise.resolvePromise.reject两个静态方法。静态方法Promise.resolve(value)可以认为是 new Promise()方法的快捷方式,这方法可以将thenable对象转换为Promise对象。在ES6 Promisethenable对象是指一个拥有then方法的对象,且这个对象的then方法和Promise对象的then方法具有相同的功能和处理过程。


2. Promise对象的使用

使用Promise处理回调函数,可以使代码比较简洁和易读,对于顺序执行的多个回调,可以使用Promise方法链式调用,即:使用重复多个then的方法进行处理。

下面我们用Promise对多个HTTP请示进行封装,并在最后一个then方法中返回多个请求中的处理结果,示例如下:

function getURL(URL) {
    return new Promise(function (resolve, reject) {
        var req = new XMLHttpRequest();
        req.open('GET', URL, true);
        req.onload = function () {
            if (req.status === 200) {
                resolve(req.responseText);
            } else {
                reject(new Error(req.statusText));
            }
        };
        req.onerror = function () {
            reject(new Error(req.statusText));
        };
        req.send();
    });
}

//
var request = {
    nodejs: function () {
        return getURL('https://nodejs.org/api/index.json').then(JSON.parse);
    },
    github: function () {
        return getURL('https://api.github.com').then(JSON.parse);
    }
};

//保存结果
function requestResults(results, value) {
    results.push(value);
    return results;
}
// [] 用来保结果的数组
var pushResult = requestResults.bind(null, []);

//请求数据
request.nodejs()
.then(pushResult)
.then(request.github)
.then(pushResult)
.then(function(results){
	console.log(results);
})
.catch(function(err){
	console.log(err);
});

在上面代码中,.then(pushResult)方法用于将多个操作中的请求结果进行保存,并在所有结果回调至最后一个then方法中。在链方法处理过程中,任意一个then出现错误,都要结束其后的then方法,并将错误回调至最后的catch方法中。