我的前端进阶学习(二)—— promise
引言本文是我在学习一个开源的 Ajax 库时所总结的内容,总共分为了几个部分
这是其中第二部分,关于 Promise
随着技术的发展,我们在编写的前端程序越来越复杂,其中有一个就是对异步任务的处理。我们希望在处理异步调用时需要对两种结果进行操作——成功操作和失败处理。再成功调用后,我们还可能将返回的结果用在另一个异步任务中,这样就会出线“函数连环嵌套”的情况。可以看看下面的示例代码:
function getSometing(data, onload, onerror) {
var xhr, results, url;
url = 'url' + data;
xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onload = function () {
// 成功回调函数
if (this.status === 200) {
results = JSON.parse(this.responseText);
onload(results);
}
};
xhr.onerror = function (e) {
// 失败回调函数
onerror(e);
};
xhr.send();
}
function handleError(error) {} // 错误处理函数
function handleResult() {} // 结果处理函数
function doSomething() {
var container = document.getElementById('container');
searchTwitter('data1', function (result1) {
searchTwitter('data2', function (result2) {
handleResult(result1, result2);
});
}, handleError);
}, handleError);
}
上面的代码是一段典型的处理Ajax
的程序,我们可以看到有许多的嵌套的回调函数在其中。这样的代码即不容易理解,看起来也不太美观,同时对错误的处理也变得十分的分散。而我在 Ajax 的源码中,学习到了一种方法正好可以处理这样的问题,这种处理模式称为promise
。
promise
的英文意思有承诺(诺言)的意思,用在这里我们可以简单的理解为:异步函数在处理的过程中返回了代表承诺的promise
对象。我们通过在对象上进行操作来完成我们的后续操作。
下面是引用别人对promise
的解释:
如何自己实现一个所谓 Promise,就是一个对象,用来传递异步操作的消息。它代表了某个未来才会知道结果的事件(通常是一个异步操作),并且这个事件提供统一的 API,可供进一步处理。
promise模式在任何时刻都处于以下三种状态之一:未完成(unfulfilled)、已完成(resolved)和拒绝(rejected)。以CommonJS Promise/A 标准为例,promise对象上的then方法负责添加针对已完成和拒绝状态下的处理函数。then方法会返回另一个promise对象,以便于形成promise管道,这种返回promise对象的方式能够支持开发人员把异步操作串联起来,如then(resolvedHandler, rejectedHandler); 。resolvedHandler 回调函数在promise对象进入完成状态时会触发,并传递结果;rejectedHandler函数会在拒绝状态下调用。
promise
我的目的不仅仅是简单了解promise
,而是自己去实现一个promise
。
先看看 Ajax 是怎样做的。具体看下面代码的注释。
下面的代码不推荐新手看,真的不推荐
function Ajax(options) {
options = options || {}
// 定义对象保存相关内容,这一个值得学习
var $public = {}
var $private = {}
// 定义 promise 需要的几种方法
$private.methods = {
then: function () { },
catch: function () { },
always: function () { },
}
// $public.get() == function(){}
// 函数返回一个 Ajax 操作的结果
$public.get = function (url, data) {
// 注意这里,这个操作返回的就是我们一个 `promise` 对象
return $private.xhrConnection(method, url, data, options);
}
$private.xhrConnection = function xhrConnection(type, url, data, options) {
// 通过 readystatechange 事件改变 `promise` 的状态
xhr.addEventListener('readystatechange', $private.ready, false)
// 返回 $private.promises 返回值 ==> allPromises
return $private.promises()
}
$private.ready = function ready() {
var xhr = this
if (xhr.readyState === xhr.DONE) {
xhr.removeEventListener('readystatechange', $private.ready, false)
$private.methods.always
.apply($private.methods, $private.parseResponse(xhr))
if (xhr.status >= 200 && xhr.status < 300) {
// 成功处理函数
$private.methods.then
.apply($private.methods, $private.parseResponse(xhr))
} else {
// 失败处理函数
$private.methods.catch
.apply($private.methods, $private.parseResponse(xhr))
}
}
}
$private.promises = function promises() {
// 设置对应的回调函数
var allPromises = {}
Object.keys($private.methods).forEach(function (method) {
allPromises[method] = $private.generatePromise.call(this, method)
}, this)
return allPromises
}
$private.generatePromise = function generatePromise(method) {
return function (callback) {
$private.methods[method] = callback
return this
}
}
return $public
}
自己实现的话可以参考下面的 《JavaScript异步编程的Promise模式》 文章,我这里没有合适的演示代码,以后有的话再补上。
总结其实promise
这个东西我很早前就接触过,但心中一直对不了解的东西有所抵触,导致自己一直都没有真正的去理解这些东西。
但如果一直因为不了解或者觉得这个东西很难,自己不想学的话,那么就永远没有机会去学习它。
扩展阅读共同学习,写下你的评论
评论加载中...
作者其他优质文章