2017-08-16 87 views
1

我真的和我的一點代碼混淆,這是一個angularjs服務。我嘗試使用Promise.all來連接作爲服務一部分的兩個promise,並將結果發送給我的控制器。 事情是由Promise.all返回的對象由兩個相同的數組組成。 這裏我的代碼,只是爲了更清楚:Promise.all()返回意想不到的值

batchModule.service('BatchService', ['$http', '$q', '$log', 'MessageboxService', function ($http, $q, $log, MessageboxService) { 

let deferred = $q.defer(); 

this.loadAll =() => { 

    promise1 =() => { 
     $http.get(_restApiPath + "/batch/?processtype=IMPORT_CUSTOMER") 
     // loadLastFiveBatch('IMPORT_CUSTOMER') 
      .then(function (response) { 
       deferred.resolve(response.data); 
       // datas.push(response1); 
       // console.log(datas); 
      }, function (error) { 
       deferred.reject(error); 
       $log.error(error); 
      }); 
     return deferred.promise; 
    }; 

    promise2 =() => { 
     $http.get(_restApiPath + "/batch/?processtype=IMPORT_LAB_MARGIN") 
     // loadLastFiveBatch('IMPORT_LAB_MARGIN') 
      .then(function (response) { 
       deferred.resolve(response.data); 
       // datas.push(response2); 
       // console.log(datas); 
      }, function (error) { 
       deferred.reject(error); 
       $log.error(error); 
      }); 
     return deferred.promise; 
    }; 

    Promise.all([promise1(), promise2()]) 
    .then(values => { 
     console.log(values); 
    }); 

}; 
}]); 

的的console.log(值)返回製成由IMPORT_CUSTOMER請求,返回2個等於陣列的一個目的,當Promise.all的第二個參數是一個恰恰promise由IMPORT_MARGIN請求返回。 我今天幾個小時一直在研究它,但我找不到任何解決方案。 我希望我很清楚,我的英語不是很好。 謝謝您的回答:-)

+2

你只有一個單一的全球'deferred',所以它有點顯而易見的,爲什麼它能夠解析爲只有一個值。當然,在第一個時候避免[deferred antipattern](https://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-avoid-it)地點! – Bergi

回答

1

問題造成的,因爲你推遲了所有的承諾使用單一。因此,那個引用的單個內容會得到解決,它將解決您的承諾呼叫的更多實例。因此,對每個請求使用不同的延遲。我仍然不喜歡使用deferred anti-pattern。而是用$http.get方法建立承諾回報。

此外,您在函數的末尾有Promise.all,這將不會運行角度摘要循環。最終,如果您要更新來自此函數的任何綁定,則不會更新UI上的綁定。考慮chainging它使用$q.all

this.loadAll =() => { 

    promise1 =() => { 
     return $http.get(_restApiPath + "/batch/?processtype=IMPORT_CUSTOMER") 
      .then(function (response) { 
       return response.data; 
      }, function (error) { 
       $log.error(error); 
       return $q.reject(error); 
      } 
     ); 
    }; 

    promise2 =() => { 
     $http.get(_restApiPath + "/batch/?processtype=IMPORT_LAB_MARGIN") 
     // loadLastFiveBatch('IMPORT_LAB_MARGIN') 
      .then(function (response) { 
       return response.data; 
      }, function (error) { 
       $log.error(error); 
       return $q.reject(error); 
      } 
     ); 
    }; 
    //return is needed if any function is trying to chain `loadAll` function. 
    return $q.all([promise1(), promise2()]) 
    .then(values => { 
     console.log("promise1", values[0]); 
     console.log("promise2", values[1]); 
    }); 

}; 
1

您的承諾實際上都會返回相同的$q.defer();承諾。因此,您需要刪除延遲的反模式(使用$q.defer()而不是return $http.get(..);),問題應該很好解決。

所以你的代碼改成這樣:

batchModule.service('BatchService', ['$http', '$q', '$log', 'MessageboxService', function ($http, $q, $log, MessageboxService) { 

    this.loadAll =() => { 

     promise1 =() => { 
      return $http.get(_restApiPath + "/batch/?processtype=IMPORT_CUSTOMER") 
       .then(response => response.data, error => { 
        $log.error(error); 
        return $q.reject(error); 
       }); 
     }; 

     promise2 =() => { 
      return $http.get(_restApiPath + "/batch/?processtype=IMPORT_MARGIN") 
       .then(response => response.data, error => { 
        $log.error(error); 
        return $q.reject(error); 
       }); 
     }; 

     $q.all([promise1, promise2]) 
     .then(values => { 
      console.log(values); 
     }); 
    }; 
}]); 
+0

非常感謝尼古拉。它確實工作得很好:-) –

+0

請注意'Promise.all'沒有與AngularJS框架及其摘要循環集成。爲了避免問題,可以使用**代替[$ q.all](https://docs.angularjs.org/api/ng/service/$q#all)。** AngularJS通過提供自己的事件來修改普通的JavaScript流處理循環。這將JavaScript分解爲經典和AngularJS執行上下文。只有在AngularJS執行上下文中應用的操作才能受益於AngularJS數據綁定,異常處理,屬性監視等。 – georgeawg

+0

將'Promise.all'更改爲'$ q.all'。幾乎只是盲目複製粘貼那部分。 :-) –