JavaScript Promise 实现(一)
2016-07-04 14:30
447 查看
大家在进行前端开发的时候,想必都经常会接触到 Promise 对象类型,这在使用或基于 jQuery、Node.js 和 ES6 等的开发过程中会经常见到。Promise 对象通常被用来设定延迟和异步的计算,例如,当一个 AJAX 请求提出后,返回一个 Promise 对象,我们可以在这个对象里追增接下来要做到事情,而这些事情其实会等到这个 AJAX 请求结束后才会被执行,而非立即。所以,Promise 通常在具有以下特性的场景中使用。
我们预期一个操作会有结果,但由于这个操作本身需要耗费一定的时间,因此该操作在当下可能并未完成。
当该操作完成并成功时,会有通知,并可能会附带有运算结果。
当该操作失败时,会有通知,并可能会附带有出错信息。
当操作完成后,无论成功与否,都不会再重新返回到原先的运行中或其它任何状态。
在 ES6 中,我们可以按照以下方式使用。
这段代码,会创建一个 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
我们预期一个操作会有结果,但由于这个操作本身需要耗费一定的时间,因此该操作在当下可能并未完成。
当该操作完成并成功时,会有通知,并可能会附带有运算结果。
当该操作失败时,会有通知,并可能会附带有出错信息。
当操作完成后,无论成功与否,都不会再重新返回到原先的运行中或其它任何状态。
在 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
相关文章推荐
- JQuery1——基础($对象,选择器,对象转换)
- java-WEB中的监听器Lisener
- Android学习笔记(二九):嵌入浏览器
- Android java 与 javascript互访(相互调用)的方法例子
- GUI - Web前端开发框架
- Extjs4.0 最新最全视频教程
- JavaScript演示排序算法
- javascript实现10进制转为N进制数
- MyEclipse Web Project转Eclipse Dynamic Web Project
- axis备忘
- 最后一次说说闭包
- Ajax
- 2019年开发人员应该学习的8个JavaScript框架
- HTML中的script标签研究
- 对一个分号引发的错误研究
- 异步流程控制:7 行代码学会 co 模块
- ES6 走马观花(ECMAScript2015 新特性)
- JavaScript拆分字符串时产生空字符的原因