2015-05-10 50 views
0

我想在我的代码下面的一个非常复杂的计算。我试图使用api https://api.github.com/repos/marklogic/java-client-api/issues?page=1&per_page=10从给定项目中的github获取错误列表。从错误列表中,我试图从相应的端点获得每个问题的相应eventscomments,例如:https://api.github.com/repos/marklogic/java-client-api/issues/291/eventshttps://api.github.com/repos/marklogic/java-client-api/issues/291/comments。 我正在使用async库。我使用waterfall函数和parallel函数为每个错误返回一个整合的JSON,以便每个问题都会有相应响应的每个问题的评论,&事件。问题是它抛出Can't set headers after they are sent错误&其指向第2行,我明白错误是什么意思,但我不知道如何解决它,因为注释掉任何有问题的行导致请求挂起,因为服务器是不发送回应。请帮忙!在此先感谢发送异常后无法设置标题错误与异步

exports.listGitHubBugs = function(req, res) { 
    var _page = req.query.page || 1; 
    var _per_page = req.query.per_page || 25; 
    var finalResult = [] 
     //console.log('url:', 'https://api.github.com/repos/marklogic/' + req.query.project + '/issues?page=' + _page + '&per_page=' + _per_page); 
    var options = { 
     url: 'https://api.github.com/repos/marklogic/' + req.query.project + '/issues?page=' + _page + '&per_page=' + _per_page, 
     headers: { 
      'User-Agent': req.query.project 
     }, 
     auth: githubAuth 
    }; 
    request(options, function(error, response, body) { 
     if (error) { 
      console.log(error); 
      res.send(error); 
     } 

     if (!error && response.statusCode === 200) { 
      var issues = JSON.parse(response.body) 

      async.waterfall([ 
       // get comments & events for all bugs and then send the response 
       function(callback) { 
        issues.forEach(function(issue) { 
          // for each bug, get comments and events 
         async.parallel([ 

          function(parallelCallback) { 
           var options = { 
            url: issue.events_url, 
            headers: { 
             'User-Agent': getProjectNameFromURL(issue.events_url) 
            }, 
            auth: githubAuth 
           }; 
           request(options, function(error, response, body) { 
            if (error) { 
             console.log('ERROR', error); 
             parallelCallback(error) 
            } 
            if (!error && response.statusCode === 200) { 
             // console.log('events:', body); 
             parallelCallback(null, body) 

            } 


           }) 
          }, 
          function(parallelCallback) { 
           var options = { 
            url: issue.comments_url, 
            headers: { 
             'User-Agent': getProjectNameFromURL(issue.comments_url) 
            }, 
            auth: githubAuth 
           }; 
           request(options, function(error, response, body) { 
            if (error) { 
             console.log('ERROR', error); 
             parallelCallback(error) 
            } 
            if (!error && response.statusCode === 200) { 
             // console.log('comments:', body); 
             parallelCallback(null, body) 
            } 


           }) 
          } 
         ], function(err, result) { 
          if (err) { 
           console.log('ERROR:', err); 
           callback(err); 
          } 
          console.log('parallel process done'); 
          issue.events = JSON.parse(result[0]); 
          issue.comments = JSON.parse(result[1]); 
          finalResult.push(issue) 
          callback(null, finalResult) // offending line#1 
         }) 
        }) // forEach end 
       } 
      ], function(err, result) { 
       if (err) { 
        res.send(err); 
       } 
       console.log('waterfall done'); 
       console.log(result); 
       res.send(result); // offending line#2 
      }) 

     } // if end 
    }) // reqest end 

} 

错误

UncaughtException: Can't set headers after they are sent. 
ERROR Error: Can't set headers after they are sent. 
    at ServerResponse.OutgoingMessage.setHeader (http.js:691:11) 
    at ServerResponse.res.set.res.header (/Users/sreddy/space/angularjs/BugTrack/node_modules/express/lib/response.js:524:10) 
    at ServerResponse.res.send (/Users/sreddy/space/angularjs/BugTrack/node_modules/express/lib/response.js:125:10) 
    at ServerResponse.res.json (/Users/sreddy/space/angularjs/BugTrack/node_modules/express/lib/response.js:191:15) 
    at /Users/sreddy/space/angularjs/BugTrack/server/api/common/common.controller.js:163:33 
    at /Users/sreddy/space/angularjs/BugTrack/server/api/common/common.controller.js:153:29 
    at /Users/sreddy/space/angularjs/BugTrack/node_modules/async/lib/async.js:254:17 
    at done (/Users/sreddy/space/angularjs/BugTrack/node_modules/async/lib/async.js:135:19) 
    at /Users/sreddy/space/angularjs/BugTrack/node_modules/async/lib/async.js:32:16 
    at /Users/sreddy/space/angularjs/BugTrack/node_modules/async/lib/async.js:251:21 

最后的工作代码

exports.listGitHubBugs = function(req, res) { 
var _page = req.query.page || 1; 
var _per_page = req.query.per_page || 25; 
var finalResult = [] 
    //console.log('url:', 'https://api.github.com/repos/marklogic/' + req.query.project + '/issues?page=' + _page + '&per_page=' + _per_page); 
var options = { 
    url: 'https://api.github.com/repos/marklogic/' + req.query.project + '/issues?page=' + _page + '&per_page=' + _per_page, 
    headers: { 
     'User-Agent': req.query.project 
    }, 
    auth: githubAuth 
}; 
request(options, function(error, response, body) { 
    if (error) { 
     console.log(error); 
     return res.send(error); 
    } 

    if (!error && response.statusCode === 200) { 
     var issues = JSON.parse(response.body) 

     async.waterfall([ 
      // get events and comments for all bugs and return the final processes list of bugs 
      function getEventsAndCommentsForAllBugs(callback) { 
       issues.forEach(function getEventsAndComments(issue, index) { 
        // for each bug, get comments and events 
        async.parallel([ 

         function getEvents(parallelCallback) { 
          var options = { 
           url: issue.events_url, 
           headers: { 
            'User-Agent': getProjectNameFromURL(issue.events_url) 
           }, 
           auth: githubAuth 
          }; 
          request(options, function(error, response, body) { 
           if (error) { 
            console.log('ERROR', error); 
            parallelCallback(error) 
           } 
           if (response.statusCode === 200) { 
            // console.log('events:', body); 
            parallelCallback(null, body) 

           } 


          }) 
         }, 
         function getComments(parallelCallback) { 
          var options = { 
           url: issue.comments_url, 
           headers: { 
            'User-Agent': getProjectNameFromURL(issue.comments_url) 
           }, 
           auth: githubAuth 
          }; 
          request(options, function(error, response, body) { 
           if (error) { 
            console.log('ERROR', error); 
            parallelCallback(error) 
           } 
           if (response.statusCode === 200) { 
            // console.log('comments:', body); 
            parallelCallback(null, body) 
           } 


          }) 
         } 
        ], function attachEventsAndComments(err, result) { 
         if (err) { 
          console.log('ERROR:', err); 
          callback(err); 
         } 
         console.log('parallel process done'); 
         issue.eventList = JSON.parse(result[0]); 
         issue.commentList= JSON.parse(result[1]); 
         finalResult.push(issue) 
         if (index === (issues.length - 1)) { 
          callback(null, finalResult) 
         } 
         // 
        }) 
       }) // forEach end 

      } 
     ], function processedBugs(err, result) { 
      if (err) { 
       res.send(err); 
      } 
      console.log('waterfall done'); 
      console.log(result); 
      res.send(result); 
     }) 

    } // if end 
}) // reqest end 
} 
+0

相关信息:[Node.js错误:发送后无法设置标头](http://stackoverflow.com/questions/7042340/node-js-error-cant-set-headers-after-they-are-sent) 。 – jfriend00

回答

0

我想通了。我为每次迭代调用parellelCallback(),而不是在循环结束时调用它。如果条件完全是必需的,那么很简单。

if (index === (issues.length-1)) { 
    callback(null, finalResult) 
    } 
0

你能提供代码的完整工作示例,这是我们可以试试。

这就是说,这个源码有几个错误。

在第一次请求时,如果发生错误,则将其写入app.response中,但不会停止执行。因此,如果发生错误,您将写入响应对象的两倍。

你应该做 if (error) { console.log(error); return res.send(error); }

,而不是 if (error) { console.log(error); res.send(error); }

然后,这是可以改变 if (!error && response.statusCode === 200) { 到 而获取问题的事件和评论出现if (response.statusCode === 200) {

同样的错误,请考虑修理它。

而且还async.//

而在async.waterfall的最终回调的最终回调。

最后,我建议你使用命名函数。这将帮助您通过提供更多有意义的错误堆栈跟踪进行调试。

例如,而不是这样做, async.prallel([function(){/* code here*/}]);

你会写 async.parallel([function nameOfTheTask(){/* code here*/}]);

考虑还用棉绒如eslint,缺少多个;可能破坏你的代码,看到http://eslint.org/

+0

非常感谢您的宝贵意见。我已经实施了您的建议并发布了最终的工作代码 – Sudhakar

相关问题