2016-04-14 7 views
0

Я запускаю последовательность из 3 сообщений ajax, и в конце мне нужно суммировать устройства из цикла while внутри каждого цикла. Сначала я получаю идентификатор сеанса, затем я получаю количество устройств и делаю цикл foreach для получения идентификаторов каждого устройства. После этого я делаю цикл while, чтобы увеличиваться в месяц с даты начала до сегодняшнего дня и получать общее потребление и сумму месяца устройства. Мне нужно общее потребление всех месяцев потребления устройств.Javascript Return loop sum

Я прокомментировал в середине функций, где я могу суммировать, и где я получаю значение 0. Я даже попытался запустить отдельную функцию, которая находится в последнем комментарии в конце, но она продолжала возвращаться не определен.

Надеюсь, что вы сможете понять идею.

var SESSION_ID =''; 
var total = parseFloat(0.0); 
$.post("http://xxx.xxxxxxxx.com/users/auth", { 
    token : "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 
    }, function (session) { 
     if(session) { 
      console.log("Session id received."); 
      SESSION_ID = session.id; 
      console.log("Looking for devices."); 
      $.post("http://xxx.xxxxxxxxxxxxxxx.com/devices/list", { 
       id : session.id 
      }, function (devices) { 
       if(devices) { 

        /* Loop trough devices to get id of each device */ 
        $.each(devices, function(index, val) { 

         /* Set start date */ 
         var targetDate = new Date(); 
         targetDate.setFullYear(2015); 
         targetDate.setMonth(2); 
         targetDate.setDate(1); 
         targetDate.setHours(0); 
         targetDate.setMinutes(0); 
         targetDate.setSeconds(0); 
         var currentDate = new Date(); 

         /* Increase 1 month until current date */ 
         while (targetDate.getMonth() !== currentDate.getMonth() || targetDate.getFullYear() !== currentDate.getFullYear()) { 
          //console.log("Month: " + (targetDate.getMonth() + 1) + "; Year: " + targetDate.getFullYear()); 
          var month = targetDate.getMonth() + 1, 
           year = targetDate.getFullYear(); 

          $.post("http://xxx.xxxxxxxxxxxxxx.com/devices/" + val.id + "/consumptions?year=" + year + "&month=" + month + "&resolution=month", { 
           id : SESSION_ID 
          }, function (consumptions) { 
           if(consumptions) { 
            $.each(consumptions, function(index, val) { 
             /* Sum each month consumption value */ 
             if(val.value !== '') { 
              total += val.value; 
             } 
            }); 

            // Return values float values Eg.: 11774.86060142517 and keeps 
            console.log(total); 
           } 
          }, "json"); 
          // Increase month 
          targetDate.setMonth(targetDate.getMonth() + 1); 

          // console.log(total) returns 0 
          console.log(total); 
         } 
        }); 

        // Total returning 0 
        // console.log(total); 
       } else { 
        console.log("No devices found."); 
       } 
      }, "json"); 
     } else { 
      console.log("No session id"); 
     } 
    }, "json"); 

    /* 
    function getMonthConsumption(device_id, device_year, device_month) { 
     $.post("http://xxx.xxxxxxxxxxxxxx.com/devices/" + device_id + "/consumptions?year=" + device_year + "&month=" + device_month + "&resolution=month", { 
      id : SESSION_ID 
     }, function (consumptions) { 
      if(consumptions) { 
       $.each(consumptions, function(index, val) { 

        if(val.value !== '') { 
         total = total + val.value; 
        } 
       }); 
       return consumptions; 
      } 
     }, "json"); 
    } 
    */ 
}); 

ответ

1

$.post вы делаете для каждого потребления устройства в месяц в цикле while является асинхронным, и для этого выполнение коды продолжается правом на печатную часть, где вы получите 0. При входе значения в консоль после всех сообщений вы увидите, что результат правильно рассчитан. Чтобы увидеть это в вашем примере удалить все console.log вызовов и заменить строку total += val.value; с функцией, которая добавляет к глобальной ценности и регистрирует новое значение в консоли, например .:

function addToTotal(value) { 
    total += value; 
    console.log(total); 
} 

... 
/* Sum each month consumption value */ 
if(val.value !== '') { 
    addToTotal(val.value); 
} 
... 

Чтобы определить, когда все сообщения заканчиваются, а затем вычисляют общую сумму, вы можете использовать jQuery-обещания, так как метод $ .post уже возвращает один. Посмотрите на jQuery.when()

EDIT

Основываясь на комментарий здесь предложенное решение с JQuery обещаниями. Сначала добавьте массив обещаний, где вы будете хранить все ваши запросы на потребление, а затем собрать все ответы и обработать их:

var SESSION_ID =''; 
var total = parseFloat(0.0); 

$.post("http://xxx.xxxxxxxx.com/users/auth", { 
    token : "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 
    }, function (session) { 
     if(session) { 
      console.log("Session id received."); 
      SESSION_ID = session.id; 
      console.log("Looking for devices."); 
      $.post("http://xxx.xxxxxxxxxxxxxxx.com/devices/list", { 
       id : session.id 
      }, function (devices) { 
       if(devices) { 

        var promises = []; 

        /* Loop trough devices to get id of each device */ 
        $.each(devices, function(index, val) { 

         /* Set start date */ 
         var targetDate = new Date(); 
         targetDate.setFullYear(2015); 
         targetDate.setMonth(2); 
         targetDate.setDate(1); 
         targetDate.setHours(0); 
         targetDate.setMinutes(0); 
         targetDate.setSeconds(0); 
         var currentDate = new Date(); 

         /* Increase 1 month until current date */ 
         while (targetDate.getMonth() !== currentDate.getMonth() || targetDate.getFullYear() !== currentDate.getFullYear()) { 
          //console.log("Month: " + (targetDate.getMonth() + 1) + "; Year: " + targetDate.getFullYear()); 
          var month = targetDate.getMonth() + 1, 
           year = targetDate.getFullYear(); 

          var postPromise = $.post("http://xxx.xxxxxxxxxxxxxx.com/devices/" + val.id + "/consumptions?year=" + year + "&month=" + month + "&resolution=month", { 
           id : SESSION_ID 
          }, "json"); 
          promises.push(postPromise); 

          // Increase month 
          targetDate.setMonth(targetDate.getMonth() + 1); 
         } 
        }); 

        // Gather all responses 
        $.when.apply($, promises).then(function() { 
         var total = 0; 
         // Here arguments will have the responses from all $.post requests added to the promises array. The actual respo 
         $.each(arguments, function(index, jqueryPostResponses) { 

          var consumptions = jqueryPostResponses[0] // first object is the data; 

          $.each(consumptions, function(index, val) { 
           /* Sum each month consumption value */ 
           if(val.value !== '') { 
            total += val.value; 
           } 
          }); 

         }); 

         return total; 
        }).then(doSomethingWithTotal); 

       } else { 
        console.log("No devices found."); 
       } 
      }, "json"); 
     } else { 
      console.log("No session id"); 
     } 
    }, "json"); 

    function doSomethingWithTotal(totalSum) { 
     $('#totalSum').text(totalSum); 
    } 
}); 

Поскольку я не могу проверить этот код, не зная фактические ответы, которые могут понадобиться для настройки кода, чтобы он работал. Вот работающий JSFiddle, который поможет вам.

Для рецидивирующего выполнения оберните $.post устройств в новой функции, которая будет выполняться с setInterval(theNewFunction, 1000 /* repeat interval in ms */);

+0

Я до сих пор не могут использовать общий внешний контур. Могу ли вы сделать и пример, как я могу достичь этого, используя или обещаю. Мне нравится запускать этот цикл через 5 или 10 секунд или, может быть, минуту. – JonnyDevv

+0

Он работал как шарм !! Большое спасибо ;) – JonnyDevv

 Смежные вопросы

  • Нет связанных вопросов^_^