JavaScript Promises

原文:JavaScript Promises
译者:涂鸦码龙

不,我不是要谈论 JavaScript 会解决一切问题的承诺。我甚至也不相信这点;) 我想谈谈几个JavaScript 库(包括 AngularJSjQueryDojoWinJS)用到的约定对象(promise object)的概念。

promise 是处理异步操作的模式。问题是当你开始一个异步操作,操作完成时需要执行一些代码。异步代码非常普遍,大部分的库已经找到了解决方案,传入回调函数。但是,每个库的作法很少有共性。让我们看看 jQuery 的例子:

此例中我们可以看到 jQuery 使用配置对象的 success 属性指定回调函数。这不是一个 promise,而是一种传入回调函数的方式。当 ajax 调用完成,它会调用 success 函数。依靠这个库做异步操作,你可能会传一组回调函数(比如 success 或者 failure)。有很多方法可以实现这一点。

约定模式(promise pattern)着手简化这个过程。异步操作简单返回一个对象叫一个约定(promise) 。promise 允许你调用 then 方法,让你指定一个或多个回调函数。让我们看看如何用 jQuery 建立一个 promise:

比较有趣的是,ajax 返回 xhr 对象实现了 promise 模式,因此我们可以调用 then 。这样做的优势是你可以链式调用,实现独立操作,完成操作时调用 done,如下所示 :

由于许多库开始着手实现 promise 模式,处理异步操作应该会更简单,不管你写什么代码(比如 NodeJS,in-browser JS 等)。promise 从另一个侧面看像什么呢?

这个模式的关键点是 then 函数可以接收两个函数,第一个用于成功回调;第二个用于失败回调,像这样:

注意到我们用了 always 指定成功或失败时的回调函数。

再看一个 AngularJS 的例子:

AngularJS 使用 $q 变量,开始调用 defer(),返回对象包含成功或失败的条件,还有 promise 本身。注意 _callMe 函数,d 变量是调用 $q.defer() 创建的,d.promise 是函数返回的,因此调用者(caller) 可以调用 promise 方法(比如 then)。当真正的异步操作执行时(此时嘲笑一下 setTimeout ),我们可以在 d 对象使用 resolve 方法,告诉 promise 我们成功完成(因此在 then 方法后面调用第一个函数)。如果我们调用 reject ,第二个方法将被调用(失败回调)。

你可以在 JSFiddle 里玩一下这些例子,看看会发生什么。Promises 的确是又简单又酷的处理异步操作的方式。我非常喜欢它,它可以简化你的代码。

更多介绍:www.promisejs.org