首頁  >  問答  >  主體

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執行邏輯是什麼?

阿神阿神2735 天前461

全部回覆(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
  • 取消回覆