代码之家  ›  专栏  ›  技术社区  ›  Bruno Ornelas

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

  •  0
  • Bruno Ornelas  · 技术社区  · 6 年前

    我有下面的代码,它请求在现在之前返回所有计划的msg,如果有一些,它将用新日期(根据repeat字段增加其值)更新“计划”集合中的每个文档,如果完成此文档更新,它将在上插入一个新文档”msgs“收藏。

    问题是我做了一个过于复杂的代码,它在最后插入了重复的msg。我怀疑在更新循环中的“scheduled”文档的异步请求完成之前,函数“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 回复  |  直到 6 年前
        1
  •  0
  •   Kaddath    6 年前

    也许你的价值观有问题 for 循环更新太快,因此异步任务之间的值已更改。如果是这样,可以尝试将使用这些值的代码包装到立即调用的函数表达式(iife)中,以便将这些值保存在内部。请参阅以下两个示例:异步任务是用超时模拟的。如果没有iife,所有执行都会显示最后一个值,因为循环在运行时已经完成。在生命周期中,值保持在达到代码时的状态。对你来说可能 date1 是有罪的,但也许 res 同样(请注意,必须在Async Success中执行日志才能看到问题):

    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);
      
    }