Sails.js控制器等待异步服务方法

时间:2015-04-26 19:09:21

标签: javascript node.js recursion promise sails.js

我不太习惯nodejs / javascript中的Promises,基本上我希望我的控制器只在我的诺言完成运行后返回一个值。

我的Sails应用程序中有以下服务。我正在使用request-promise模块向facebook graph 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});			
});  

但是在我的服务承诺结束之前控制器返回0,当我查看日志时我可以看到它仍在执行循环。

如何让我的控制器在返回之前等待所有内容结束,我认为那是.then()工作。

2 个答案:

答案 0 :(得分:2)

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

var countPhotos = Facebook.countTaggedPhotos()

你将countPhotos设置为等于countTaggedPhotos()。然后()返回。在这种情况下,它不会返回照片数量。你可以访问照片数量的唯一地方是.then。

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

周围的代码
return http(options).then(function(data){...

因为在那里,你引用了照片,但我不知道它是如何实际提供给控制器中的.then()的。

答案 1 :(得分:2)

由于这个问题,经过几个小时撞到墙上,我找到了问题的根源和解决方案。

问题的根源:递归

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

一旦递归开始,我没有得到任何等待它们的承诺,导致我的问题,当第一个承诺结束时,他执行.then()回调,返回数组中的0张照片并释放控制器返回之前在其他页面上结束处理。另一个错误是我在整个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,请随时发表评论。