未达到异步回调,响应挂起

Posted

技术标签:

【中文标题】未达到异步回调,响应挂起【英文标题】:Not reaching aync callback, response hangs 【发布时间】:2015-11-23 14:20:30 【问题描述】:

我遇到了一个问题,我不确定要采取什么步骤来解决它。现在所有数据都被正确检索但是 responseCallback 永远不会触发,因此我没有到达 res.json 与响应数组的调用。这里的任何指导将不胜感激!谢谢。

为了澄清问题在于 aysnc.each 回调。

  var updatedBusinesses = [];
  googleplaces.radarSearch(location:"lat,long",radius:"10000",keyword:"keywordhere",function(err,response)
   if(err)return next(err);

   async.each(response.results,function(currResponse,responseCallback)
    Business.findOne("placesId":currResponse.place_id,"claimed":true).populate(path:'services',select:'').exec(function(err,business)
     if(err)return next(err);

     if(business !== null)
       Service.populate(business.services,path:'employees',select:'_id appointments firstName lastName username avatarVersion',function(err,newBusiness)
        if(err)return next(err);

        googleplaces.placeDetailsRequest(placeid:business.placesId,function(error,placesResult)
         if(error)return responseCallback(error);

         console.log("RESULT OF THE GOOGLE PLACES DETAIL SEARCH")
         placesResult.result.info = business;
         updatedBusinesses.push(placesResult.result);
         // Here the data is populated and correct.
         // console.log(updatedBusinesses)
         responseCallback();

       );
     )
   
 )
,function(err)
   if(err)return next(err);
   console.log("called")
   res.json(updatedBusinesses);
 )
)

这是我希望将更新的业务信息返回给客户的地方,但是这永远不会触发。

,function(err)
   if(err)return next(err);
   console.log("called")
   res.json(updatedBusinesses);
 )
)

【问题讨论】:

这里有多个回调。你能确定哪些没有被解雇吗? 是的,抱歉,async.each responseCallback 你是否到达了这个``` // console.log(updatedBusinesses)``,如果你取消注释它会给你正确的结果吗? 是的,代码到达了该语句并且确实到达了。这正是我想返回给客户端的数据。 那么你的回调应该是 responseCallback(null, updatedBusinesses); 【参考方案1】:

将您的代码 responseCallback(); 更改为 responseCallback(null, [your-result]); 我认为应该可以完成这项工作

var updatedBusinesses = []; googleplaces.radarSearch(location:"lat,long",radius:"10000",keyword:"keywordhere",function(err,response)

if(err)return next(err);

async.each(response.results,function(currResponse,responseCallback)    Business.findOne("placesId":currResponse.place_id,"claimed":true).populate(path:'services',select:'').exec(function(err,business)
 if(err)return next(err);

 if(business !== null)
   Service.populate(business.services,path:'employees',select:'_id appointments firstName lastName username avatarVersion',function(err,newBusiness)
    if(err)return next(err);

    googleplaces.placeDetailsRequest(placeid:business.placesId,function(error,placesResult)
     if(error)return responseCallback(error);

     console.log("RESULT OF THE GOOGLE PLACES DETAIL SEARCH")
     placesResult.result.info = business;
     updatedBusinesses.push(placesResult.result);
     // Here the data is populated and correct.
     // console.log(updatedBusinesses)
     responseCallback(null, updatedBusinesses);

   );
 )
 ) ,function(err, updatedBusinesses)
   if(err)return next(err);
   console.log("called")
   res.json(updatedBusinesses);
 )
)

【讨论】:

感谢 bianca,但是我已经尝试过这个解决方案,但它不起作用。基于位于此处的异步库文档:github.com/caolan/async#each 我认为我不能将第二个参数传递给该回调。当我尝试这种方法时,没有数据被传递..这意味着 updatedBusinesses 数组没有被传递到回调中。响应仍然挂起。【参考方案2】:

async.each() 期望每次迭代都会调用一个回调 (responseCallback)。如果它没有被调用,它就会坐在那里等待它。这就是为什么您的更新业务部分永远不会被调用的原因。

在您的 async.each() 内部,有许多地方调用 next(),这不是 async.each() 的迭代回调 (responseCallback)。这是正确调用回调的修改后的代码:

var updatedBusinesses = [];

googleplaces.radarSearch(location:"lat,long",radius:"10000",keyword:"keywordhere",function(err,response)
    if(err)return next(err);

    async.each(response.results,function(currResponse,responseCallback)
        Business.findOne("placesId":currResponse.place_id,"claimed":true).populate(path:'services',select:'').exec(function(err,business)
            if(err)
              return responseCallback(err);// <== calling responseCallback instead of next() 
             

            // in case of business === null/undefined, I'm not seeing any 
            // callback getting called, it needs to be called inside 
            // async.each() no matter which condition it is
            if (!business) 
               // call responseCallback to continue on with async.each()
                return responseCallback();
            
            Service.populate(business.services,path:'employees',select:'_id appointments firstName lastName username avatarVersion',function(err,newBusiness)
                if(err)
                  return responseCallback(err);// <== calling responseCallback instead of next() 
                

                googleplaces.placeDetailsRequest(placeid:business.placesId,function(error,placesResult)
                    if(error)return responseCallback(error);

                    console.log("RESULT OF THE GOOGLE PLACES DETAIL SEARCH")
                    placesResult.result.info = business;
                    updatedBusinesses.push(placesResult.result);
                    // Here the data is populated and correct.
                    // console.log(updatedBusinesses)
                    responseCallback();
                );
            )
        )
    ,function(err)
        if(err)return next(err);
        console.log("called");
        res.json(updatedBusinesses);
    );
); 

所以现在对于 async.each() 中的每个条件都会调用 responseCallback()。它现在应该归结为代码的“更新的业务信息”部分。

【讨论】:

谢谢!这很有意义。

以上是关于未达到异步回调,响应挂起的主要内容,如果未能解决你的问题,请参考以下文章

Promise相关

应用程序如何处理异步响应 - 通过回调

基于先前调用的响应的异步调用,避免回调地狱

NodeJS 异步回调未完成和渲染把手模板

tcp异步机制

超时 - 在 jest.setTimeout 指定的 5000 毫秒超时内未调用异步回调