2015-04-26 38 views
2

我不是很习惯nodejs/javascript中的Promise,基本上我希望我的控制器只有在我的承诺完成运行后才返回一个值。Sails.js控制器等待异步服务方法

我在我的Sails应用程序中有以下服务。我正在使用请求承诺模块向facebook图形API发出HTTP请求。

return http(options).then(function(data){ 
 

 
     var res = JSON.parse(data); 
 

 
     if(!res || res.error) { 
 
     console.log(!res ? 'error occurred while loading photos' : res.error); 
 
     return; 
 
     } 
 

 
     for (var photoIndex in res.data) { 
 

 
     var photo = res.data[photoIndex]; 
 

 
     if (photo.tags) { 
 

 
      for(var tagIndex in photo.tags.data){ 
 

 
      var tag = photo.tags.data[tagIndex]; 
 

 
      console.log('TAG_ID: '+tag.id + ' -> TARGET_ID: ' + target); 
 

 
      if (tag.id == target) { 
 
       photos.push(photo); 
 
      } 
 

 
      } 
 

 
     } 
 
     } 
 

 
     if (res.paging && res.paging.next) { 
 
     console.log('recursion in action!!'); 
 
     myself(id, target, accessToken, decodeURIComponent(res.paging.next)); 
 
     }

我的控制器:

var countPhotos = Facebook.countTaggedPhotos(requesterId, targetId, accessToken).then(function(photos){ 
 
    return res.json({photos: photos.length}); \t \t \t 
 
});

不过控制器返回0,我的服务承诺结束前,当我看向日志我可以看到它仍在执行循环。

我怎么才能让我的控制器等待一切结束才回来,我以为是.then()工作。

回答

2

因为这个问题,经过几个小时的撞击,我找到了问题的根源和解决方案。

根的问题:的递推

myself(id, target, accessToken, decodeURIComponent(res.paging.next)); 

一旦递归开始我没有得到任何承诺等待他们,导致我的问题,在第一承诺结束,他执行的.then()回调返回数组中的0张照片并释放控制器以在endind处理其他页面之前返回。另一个错误是我在整个countTaggedPhotos方法中进行递归,只改变了http回调。

解决方法:嵌套承诺

var promiseHttp = http(options).then(function myself(data){ 
 

 
    var res = JSON.parse(data); 
 

 
    if(!res || res.error) { 
 
    console.log(!res ? 'error occurred while loading photos' : res.error); 
 
    return; 
 
    } 
 

 
    for (var photoIndex in res.data) { 
 

 
    var photo = res.data[photoIndex]; 
 

 
    if (photo.tags) { 
 

 
     for(var tagIndex in photo.tags.data){ 
 

 
     var tag = photo.tags.data[tagIndex]; 
 

 
     if (tag.id == target) { 
 
      photos.push(photo); 
 
     } 
 

 
     } 
 

 
    } 
 
    } 
 

 
    if (res.paging && res.paging.next) { 
 

 
    var opt={ uri: decodeURIComponent(res.paging.next), method: 'GET' }; 
 
    return http(opt).then(myself); 
 

 
    } 
 

 
}); 
 

 
return promiseHttp.return(photos);

现在我的控制器能够等待每一页完成它的处理,并返回正确的照片。

我不知道这个解决方案是否是最好的,但它的工作原理。如果任何人有什么补充,一些最佳实践或somenthing,随时发表评论。

2

当你说这是一个.then()工作时,你是对的。当你说

var countPhotos = Facebook.countTaggedPhotos() 

你设定)countPhotos等于什么countTaggedPhotos(则()回报。在这种情况下,它不会返回照片的数量。您可以访问的照片数量唯一的地方在那里。然后。

为了进一步帮助您,您需要提供您的周围

return http(options).then(function(data){... 

,因为在那里,你引用的照片的代码,但我不知道怎么这实际上是提供给。然后()在你的控制器。