您的位置:首页 > Web前端 > JavaScript

JavaScript Promise 实现(一)

2016-07-04 14:30 447 查看
大家在进行前端开发的时候,想必都经常会接触到 Promise 对象类型,这在使用或基于 jQuery、Node.js 和 ES6 等的开发过程中会经常见到。Promise 对象通常被用来设定延迟和异步的计算,例如,当一个 AJAX 请求提出后,返回一个 Promise 对象,我们可以在这个对象里追增接下来要做到事情,而这些事情其实会等到这个 AJAX 请求结束后才会被执行,而非立即。所以,Promise 通常在具有以下特性的场景中使用。

我们预期一个操作会有结果,但由于这个操作本身需要耗费一定的时间,因此该操作在当下可能并未完成。
当该操作完成并成功时,会有通知,并可能会附带有运算结果。
当该操作失败时,会有通知,并可能会附带有出错信息。
当操作完成后,无论成功与否,都不会再重新返回到原先的运行中或其它任何状态。
在 ES6 中,我们可以按照以下方式使用。

var promise = new Promise(
function (resolve, reject) {
// 主要业务逻辑。
setTimeout(function () {
// 主要业务逻辑里的回调。
var now = new Date();
if (now.getSeconds() % 2 === 0)
// 切换为成功状态,并触发回调。
resolve(now);
else
// 切换为失败状态,并触发回调。
reject(now);
}, 1000);
});

// 注册回调。
promise.then(
function (value) {
// 成功时的回调。
console.debug("Success", value);
},
function (reasone) {
// 失败时的回调。
console.debug("Error", reasone);
});

这段代码,会创建一个 Promise 对象,并注册了一组回调(可以注册多组),以分别在其成功和失败时会触发指定的事件。而在 Promise 对象内注册的业务逻辑,则只是简单地制定在一秒钟后根据当前时间状况,确定是进入成功或失败的逻辑分支,并将结果或出错信息做为参数返回,触发刚才提及的那些回调。具体说来,当运行这段代码时,会按照以下步骤进行。

首先,创建了一个 Promise 对象,里面的传入参数是一个函数,做为该 Promise 的主要业务逻辑。
执行该传入函数,并为该函数传入两个参数,分别是成功和失败时的触发器。
对 Promise 执行结束后的事件注册。可以注册多组事件,每组包括一个成功和一个失败,也可以是成功或失败的一个。这些事件组将按照先后顺序执行。
主要业务逻辑的异步回调此时可能被执行到。
主要业务逻辑可能会将当前状态切换为成功或失败,由此会自动调用该类注册的事件。
在调用成功或失败的事件时,会按照注册的顺序来执行。如果在执行成功事件时发生错误,会调用对应的失败事件(如果有)。
如果成功或失败时间中有返回值,则会自动创建下一个 Promise 对象,以便将延迟异步过程和对应的结果逐个传递下去。
说了这么多,我要开始研究如何实现该类了。

既然说到这是一个类,那么,考虑到前面说的需求,我们先来看看其应该具备哪些方法和属性,以及看看构造函数是怎样的。

首先,需要一个构造函数,我们需要传入一个函数,即所需的主要业务逻辑,该函数可能是个运算量较大或等待时间较长的函数。该函数需要支持两个参数,分别是成功和失败时的触发器。每个触发器其实又是一个函数,并可接受可选的运算结果或出错信息。
其次,还需要一个成员方法,用于注册成功和失败的回调。该方法需要提供两个参数,即成功后的回调,和失败后的回调。这些回调当然也都是方法啦,并支持传入可选的参数,这些参数其实就是成功时的运算结果或失败时的出错信息。同时,这些回调也可以返回结果,这个结果将被用于自动生成下一个 Promise 对象,供之后继续传递。
于是乎,我们得到以下代码。为了便于从基本说明,以下代码均使用 ES5 书写。

var Promise = function (executor) {
// ToDo: Implement it.
};
Promise.prototype.then = function (onfulfilled, onrejected) {
return Promise(function (resolve, reject) {
// ToDo: Implement it.
});
};
Promise.prototype.catch(onrejected) {
return this.then(null, onrejected);
}


显然,我们还需要一些变量或字段来存储一些的信息。

状态信息,如进行中、成功、失败。
成功时的运算结果或失败时的出错信息。
因此,我们需要现在构造函数中初始化状态信息。

this._state = null;

该值为布尔值,当为 true 时表示成功,false 时为失败,默认为 null 表示运行中。而成功或失败后的结果,我们后面预计使用 this._value 来存储。

现在,我们已经大致拟定好了一个接口,接下来的实现,且看后续文章。

【未完待续】

文章类型及复杂度:Web 前端开发进阶。

节选翻译自 MSDN 博文 JavaScript Promise,内容有所调整。
http://blogs.msdn.com/b/kingcean/archive/2016/03/25/promise-in-web.aspx
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Web JavaScript