2015-05-07 190 views
3

我想我可能會錯過關於承諾如何工作的根本原因,因爲我似乎沒有得到我期望的結果,所以希望有人能糾正我的想法。q承諾在完成之前解決?

在這種情況下,這是一個相對容易的調用。我有一個角色工廠,除了其他的東西從API獲取一些數據(這會調用mongodb)。 由於存在$ http請求(這是異步的),因此我將http調用封裝在$ q函數中,如果成功則返回resolve,如果出現錯誤則返回reject

factory.loadLayout = function (layoutName) { 
    return $q(function(resolve, reject){ 
     $http.get('/api/getlayout/'+layoutName) 
      .success(function (data) { 
       layout = data; 
       console.log("Got " + layout.name); 
       resolve('OK'); 
      }) 
      .error(function(data,status,headers,config){ 
       reject(new Error(status)); 
      }); 


    }); 
} 

然後我有另一個功能是依賴於第一功能收集的數據,稱爲getButtonId,但據我所知,即使它被包裹在.then,現在看來似乎是在諾言解決之前呼籲。

var promise = padArea.loadLayout(layoutName); 
    promise.then(padArea.getButtonId('A0')); 

那麼我錯過了什麼?

== == UPDATE所以 使用q.defer

factory.loadLayout = function (layoutName) { 
    var defer = $q.defer() 
     $http.get('/api/getlayout/'+layoutName) 
      .success(function (data) { 
       layout = data; 
       console.log("Got " + layout.name); 
       defer.resolve('OK'); 
      }) 
      .error(function(data,status,headers,config){ 
       defer.reject(new Error(status)); 
      }); 
    return defer.promise; 
} 

還沒工作,我希望嘗試同樣的事情,和HTTP已完成之前。然後裏面的功能仍稱。

==更新2 == 好了,得到它的工作(如果我只是呼籲在工廠裏。然後裏面的功能,它直接調用它,但是,如果我在一個功能,把它包裝成以下時,突然的作品。任何人都可以解釋爲什麼雖然,因爲對我來說,好像包裹調用函數內部函數應該只從調用該函數沒有區別。

padArea.loadLayout(layoutName).then(function(result){ 
    padArea.getButtonId('A0') 
}); 

奇怪的是,只要我打包第二個電話(在.then內),我的原始代碼也可以工作。

+2

'$ q'已經返回已解決的承諾。 –

+0

那麼,如何讓它等到它想要解決承諾。 – vrghost

+1

我無法重現這一點:http://plnkr.co/edit/rlvnuTvm1b0C1fh0Oabk?p=preview *但*'$ http'無論如何返回一個承諾,所以你可以刪除所有'$ q'功能和返回'$ http.get'調用,而功能應該是相同的。 –

回答

3

只需使用$http承諾:

factory.loadLayout = function (layoutName) { 
    return $http.get('/api/getlayout/'+layoutName) 
     .success(function (data) { 
      layout = data; 
      console.log("Got " + layout.name); 
      resolve('OK'); 
     }) 
     .error(function(data,status,headers,config){ 
      reject(new Error(status)); 
     }); 
} 

然後使用它...

factory.loadLayout(param).then(function (response) { ... });

OR

我看到你正在嘗試做的。而是創建一個從$q

factory.loadLayout = function (layoutName) { 
    var defer = $q.defer(); 
    $http.get('/api/getlayout/'+layoutName) 
     .success(function (data) { 
      layout = data; 
      console.log("Got " + layout.name); 
      defer.resolve('OK'); 
     }) 
     .error(function(data,status,headers,config){ 
      defer.reject(new Error(status)); 
     }); 
    return defer.promise; 
} 
+1

這些解決方案似乎都不起作用。 $ q.defer不會拋出任何錯誤,但.then語句中的函數在http.get被調用之前仍然運行(嘗試使用帶有resolve和reject的$ http,只是得到了這些未定義的地方。例如上面) – vrghost

+0

第二個工作,只要它被包裝在一個函數中 – vrghost

+0

因爲'.then'需要一個函數作爲它的參數,所以你必須把它包裝在一個函數中,其他的選項是'.then(padArea .getButtonId.bind(padArea,'A0'))' –

2

遞延你也可以使用$ q.defer():

deferred = $q.defer(); 

$http.get('/api/getlayout/'+layoutName) 
    .success(function (data) { 
     layout = data; 
     deferred.resolve("OK"); 
    }) 
    .error(function (data,status,headers,config){ 
     deferred.reject(new Error(status)); 
    }) 

return deferred.promise; 

這可能是一個小更一般的,如果你不只是在做一個HTTP請求,並讓你控制回報。