首页 > 代码库 > 翻译:JavaScript Promises and AngularJS $q Service

翻译:JavaScript Promises and AngularJS $q Service

翻译:JavaScript Promises and AngularJS $q Service

原文:http://www.webdeveasy.com/javascript-promises-and-angularjs-q-service/

原文时间:2014年9月30号

      一个promise(延缓)是处理异步开发简单而强大的方法。CommonJS 维基百科列出了 几个promise模式的实施提议。AngularJS自己的promise实现方法是受kris Kowal‘s Q的方法启发的。在这篇文章中我会介绍promises,它的目的和怎么通过AngularJS $q的promise服务开发的教程。


      Promise(延缓)目的

    在JavaScript中,异步方法通常通过调用回调方法来实现成功或失败的处理。比如说浏览器的地理位置api,获取地理坐标时就需要成功或者失败的回调方法。

function success(position) {  var coords = position.coords;  console.log(‘Your current position is ‘ + coords.latitude + ‘ X ‘ + coords.longitude);}function error(err) {  console.warn(‘ERROR(‘ + err.code + ‘): ‘ + err.message);}navigator.geolocation.getCurrentPosition(success, error);

      另一个例子就是xhr请求(ajax请求),它有一个onreadystatechange回调方法,当readyState改变时就会调用它。

var xhr = new window.XMLHttpRequest();xhr.open(‘GET‘, ‘http://www.webdeveasy.com‘, true);xhr.onreadystatechange = function() {    if (xhr.readyState === 4) {        if (xhr.status === 200) {            console.log(‘Success‘);        }    }};xhr.send();

      Javascript中还有许多其他的异步例子,下面讨论麻烦的多个异步方法运行

 串行(无尽金字塔)

    假设现在又N种异步方法需要串行运行:async1(success, failure)async2(success, failure), …, asyncN(success, failure),一个接一个直到成功,每个方法都有成功和失败的回调,那么代码就是这样:

async1(function() {    async2(function() {        async3(function() {            async4(function() {                ....                    ....                        ....                           asyncN(null, null);                        ....                    ....                ....            }, null);        }, null);    }, null);}, null); 

    这就是著名的回调金字塔(callback pyramid of doom)。虽然还有更好的写法(把回调流分隔成函数),但是这种方式还是很难读懂和维护。

并行

    假设我们有N个异步方法,async1(success, failure)async2(success, failure), …, asyncN(success, failure) ,我们需要让他们并行运行,再在最后弹出一个消息。每个方法都有成功和失败的回调,那么代码就是这样:

var counter = N;function success() {    counter --;    if (counter === 0) {        alert(‘done!‘);    }}async1(success);async2(success);........asyncN(success);

      我们声明了一个变量counter,让它的值为N,每当一个方法成功了,就减一,然后检测是否为零,也就是是否执行到最后一个了。这种方法使用起来既麻烦又不利于维护,特别是当每个异步方法还有参数要传到success()方法里的时候,那样我们还要保存每次运行的结果。

      在上面两个例子里,在一个异步操作过程中,我们必须要指定成功的回调。也就是说,当我们用回调时,异步操作的继续需要一个引用,但是它的下一步操作也许是与自己无关的。这就导致了很难重复使用和测试的紧密耦合模块和服务。

翻译:JavaScript Promises and AngularJS $q Service