【问题标题】:Sails.js controller waits for async service methodSails.js 控制器等待异步服务方法
【发布时间】:2015-07-05 02:35:30
【问题描述】:

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

我的 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() 工作。

【问题讨论】:

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


    【解决方案1】:

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

    var countPhotos = Facebook.countTaggedPhotos()
    

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

    为了进一步帮助您,您需要提供围绕您的代码

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

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

    【讨论】:

      【解决方案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);

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

      我不知道这个解决方案是否是最好的,但它确实有效。如果有人有什么要补充的,一些最佳实践或其他东西,请随时发表评论。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-10-14
        • 1970-01-01
        • 1970-01-01
        • 2020-02-11
        • 2015-04-26
        • 2014-05-15
        • 2015-02-13
        • 1970-01-01
        相关资源
        最近更新 更多