【问题标题】:Node: Requests inside requests Inside looping节点:请求内部的请求内部循环
【发布时间】:2018-11-27 13:09:45
【问题描述】:

我有下面的代码,它请求在现在之前返回所有预定的消息,如果有的话,它会用新日期更新“预定”集合中的每个文档(根据重复字段增加其值),如果此文档更新完成,它会在“msgs”集合中插入一个新文档。

问题是我做了一个过于复杂的代码,它在最后插入了重复的消息。我怀疑函数“insertScheduledMsgs”在异步请求更新循环内的“计划”文档完成之前再次被调用,因此下次调用该函数时,计划文档仍然具有旧日期。

如何更简单地解决此问题?

下面你可以看到整个代码:

function insertScheduledMsgs() {

request.get( {
    headers: { 'Authorization':'Bearer ' + token },
    url: urlApi + "scheduleBeforeOrAfterNow?msgsPosition=before"
}, function( error, response, body ){
    if ( !error && response.statusCode == 200 ) {

        results = JSON.parse( body );

        for ( let res in results ){
            let bodyMsg = "",
                bodySchedule = "",
                log,
                scheduleDate = (Number( results[res].date ) + ( Number( results[res].repeat ) * 60 * 1000)),
                date1 = new Date(results[res].date),
                date2 = new Date();

            bodyMsg += 'user=' + results[res].user;

            if ( results[res].media ) {
                bodyMsg += '&media=' + results[res].media;
            }

            bodyMsg += '&txt=' + results[res].txt;
            bodyMsg += '&time=' + results[res].time;
            bodyMsg += '&layout=' + results[res].layout;
            bodyMsg += '&boxes=' + results[res].boxes;

            bodySchedule += '_id=' + results[res]._id;
            bodySchedule += '&date=' + scheduleDate;

            if( date1.setSeconds(0,0) <=  date2.setSeconds(0,0) ) {

                request.put( {
                    headers: { 'content-type' : 'application/x-www-form-urlencoded', 'Authorization':'Bearer ' + token },
                    url: urlApi + "schedule",
                    body: bodySchedule
                }, function( errorSchedule, responseSchedule, body ){

                    logs({
                        event: "date updated in scheduled msg",
                        date: new Date().getTime()
                    }, token);

                    if( date1.setSeconds(0,0) ===  date2.setSeconds(0,0) ) {

                        request.post( {
                            headers: { 'content-type' : 'application/x-www-form-urlencoded', 'Authorization':'Bearer ' + token },
                            url: urlApi + "msgs",
                            body: bodyMsg
                        }, function( errorMsg, responseMsg, body ){

                            logs({
                                event: "scheduled msg sent to monitor / tv",
                                date: new Date().getTime()
                            }, token);

                            if ( (Number(res) + 1) === results.length ) {

                                insertScheduledMsgs();
                            }
                        } );
                    } else {

                        if ( (Number(res) + 1) === results.length ) {

                            insertScheduledMsgs();
                        }
                    }                   
                } );
            } else {

                if ( (Number(res) + 1) === results.length ) {

                    insertScheduledMsgs();
                }
            }
        };

    } else {

        insertScheduledMsgs();

    }
} );

};

【问题讨论】:

  • 您确定存储在res 中的密钥是数字的吗?如果是,为什么不使用数字索引 for 循环?如果没有,请注意转换(您是否尝试过记录 (Number(res) + 1)results.length 以查看它们何时匹配?)
  • 循环工作正常,results.length 工作正常。问题在于同步循环 x 异步请求
  • 我记录了这些值,正如我所说,它按预期工作......也许它不是你指出的最好的实现,但这不是错误的原因。目的是定义处理请求和循环的最佳方式,一旦一个是异步的,另一个不是。我从来没有打算让任何人为我调试我的应用程序。

标签: javascript node.js ajax mongodb asynchronous


【解决方案1】:

您的 for 循环中的一个值可能存在问题,因为它更新得太快,以至于异步任务之间的值发生了变化。如果是这种情况,您可以尝试将使用这些值的代码包装到立即调用函数表达式 (IIFE) 中,以便将值保留在内部。请参阅以下 2 个示例:异步任务模拟超时。如果没有 IIFE,所有执行都会显示最后一个值,因为循环在运行时已经完成。使用 IIFE,值将保持与达到代码时的值相同。在您的情况下,date1 可能是有罪的,但也可能是res(请注意,您必须在异步成功中进行日志才能看到问题):

var arr = [{val: 'test1'}, {val: 'test2'}, {val: 'test3'}],
    i, l = arr.length, value;

for(i = 0; i < l; i++){
  
  value = arr[i];
  
  console.log('LOOPING i / value: ', i, value);
  
  setTimeout(function(){
    console.log('WITHOUT IIFE WRAP i / value: ', i, value);
  }, 1);
  
  (function(_i, _value){
    setTimeout(function(){
      console.log('WITH IIFE WRAP i / value: ', _i, _value);
    }, 1);
  })(i, value);
  
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-04
    • 2023-03-09
    • 1970-01-01
    • 2017-02-24
    • 2011-12-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多