搜索

首页  >  问答  >  正文

angular.js - angularjs $q的promise 怎么解决嵌套的ajax问题?

问题一:我需要用第一次发送ajax请求回的数据作为第二次ajax的参数,而第二次的ajax是在第一次ajax的回调函数里发送的。但是这里有问题!就是第二次ajax返回的数据不能赋值给全局对象的属性,不知道是不是掉到坑里了。所以想用$q解决。
问题二:那这个例子来说吧,
// $q 是内置服务,所以可以直接使用
ngApp.factory('UserInfo', ['$http', '$q', function ($http, $q) {
return {

query : function() {  
  var deferred = $q.defer(); // 声明延后执行,表示要去监控后面的执行  
  $http({method: 'GET', url: 'scripts/mine.json'}).  
  success(function(data, status, headers, config) {  
    deferred.resolve(data);  // 声明执行成功,即http请求数据成功,可以返回数据了  
  }).  
  error(function(data, status, headers, config) {  
    deferred.reject(data);   // 声明执行失败,即服务器返回错误  
  });  
  return deferred.promise;   // 返回承诺,这里并不是最终数据,而是访问最终数据的API  
} // end query  

};
}]);
deferred.resolve 是为了延迟执行吗?那如果能在回调函数里面写逻辑为什么还要多此一举的延迟执行呢?
问题三:为什么说deferred.promise返回的承诺是最终数据api?这个promise的作用是什么?
问题四:promise.then执行逻辑是什么?

阿神阿神2795 天前491

全部回复(1)我来回复

  • PHPz

    PHPz2017-05-15 17:05:42

    在回答你所有的问题之前,我先对你的示例代码做些简单说明!!

    你的示例代码是一个典型的Promise的反面教材,其特征就是:无目的的创建deferred对象,徒增代码复杂度。关于这点,可以看这里anti-pattern:

    纠正问题之后,我们再来回头谈你的问题。

    首先,当你意识到自己正在忍受callback hell的时候,恭喜你,在javascript这条路上,你算上道儿了。那么解决之道有哪些呢?我们最近常见的有:

    • Promise

    • generator配合co

    • async/await

    关于这几种方式的详细介绍,我没仔细翻别人的答案(或许有更好的),只能把自己之前写的贴出来javascript里的异步

    OK,介绍了解决callback hell的几种常见方式,再回头来说你的callback hell的几种常见方式,再回头来说你的Promise问题

    问题一:我需要用第一次发送ajax请求回的数据作为第二次ajax的参数,而第二次的ajax是在第一次ajax的回调函数里发送的。但是这里有问题!就是第二次ajax返回的数据不能赋值给全局对象的属性,不知道是不是掉到坑里了。所以想用$q解决。

    既然我们寄希望于Promise能够解决回调地狱的问题,拿肯定不会再是使用回调的方式,你的疑惑是对的,可你的问题是没有充分理解Promise能够解决回调地狱的问题,拿肯定不会再是使用回调的方式,你的疑惑是对的,可你的问题是没有充分理解

    是这么工作的。我先举个例子:
    var call1 = function(cb) {
        setTimeout(function() {
            cb('call1');
        }, 10);
    };
    
    var call2 = function(param1, cb) {
        setTimeout(function() {
            cb(param1 + ' + call2');
        }, 10);
    };
    
    call1(function(param1) {
        call2(param1, function(param2) {
            console.log(param2); //call1 + call2
        });
    });

    call2依赖了call1的结果。如果用Promise这是一个典型的回调依赖,call2依赖了call1的结果。如果用

    改写,应该是什么样子呢?
    var call1 = function() {
        return new Promise(function(resolve, reject) {
            setTimeout(function() {
                resolve('call1');
            }, 10);
        });
    };
    
    var call2 = function(param1) {
        return new Promise(function(resolve, reject) {
            setTimeout(function() {
                resolve(param1 + ' + call2');
            }, 10);
        });
    };
    
    call1()
        .then(function(param1) {
            return call2(param1);
        })
        .then(function(param2) {
            console.log(param2); //call1 + call2
        });

    deferred对象,call1call2本身返回Promise对象即可; 2. resolve几乎扮演了之前cb的角色; 3. 当执行call1call2时,不塞入回调,而是通过then拿到返回结果 4. 尤其return call2(param1);这个地方,真的不要再度嵌套(很多初入Promise的选手犯的错),直接返回,下一个then这里有几个要注意的地方,1. 无需不必要的deferred对象,call1call2本身返回

    对象即可; 2. resolve几乎扮演了之前cb的角色; 3. 当执行call1call2时,不塞入回调,而是通过
    拿到返回结果 4. 尤其return call2(param1);这个地方,真的不要再度嵌套(很多初入

    的选手犯的错),直接返回,下一个里就能拿到结果

    问题二:那这个例子来说吧

    then

    这就是最早说的问题,你过度反应了,明显把简单问题复杂化了,这么写足矣:🎜
    ngApp.factory('UserInfo', ['$http', '$q', function($http, $q) {
        return {
            query: function() {
                return $http({method: 'GET', url: 'scripts/mine.json'});
            }
        };
    }]);
    🎜调用的地方,直接用🎜就好了:🎜
    UserInfo
        .query()
        .then(function(data){
            console.log(data);//这不就是结果喽!
        });

    第三、四个问题都是源于对Promise本身的实现没概念,我之前写过一个小教程,教大家自己手写一个Promise的简单实现,建议你跟着做做,先对Promise本身有个大概了解,一步步来手写一个Promise

    回复
    0
  • 取消回复