节点:内部请求中的请求内部循环

时间:2018-11-27 13:09:45

标签: javascript node.js ajax mongodb asynchronous

我有下面的代码,该代码要求现在返回所有预定的消息,如果有的话,它将用新的日期更新“预定”集合中的每个文档(根据重复字段增加其值),如果此文档更新完成,则会在“ 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();

    }
} );

};

1 个答案:

答案 0 :(得分:0)

也许您的for循环中的一个值更新得太快了,以至于异步任务之间的值已更改,这可能是一个问题。如果是这样,您可以尝试将使用这些值的代码包装到立即调用的函数表达式(IIFE)中,以便将这些值保留在内部。请参见下面的两个示例:异步任务是使用超时来模拟的。如果没有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);
  
}