2015-05-07 151 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请求,并让你控制回报。