Значения обещания в JS внутри цикла for - PullRequest
0 голосов
/ 14 июля 2020

Я потерялся в обещанной земле и действительно мог бы воспользоваться некоторыми советами. Я исчерпал себя поиском множества SO-вопросов (2-3 часа чтения решений + документация), связанных с этой, казалось бы, общей проблемой, и чувствую, что просто не понимаю ее.

Обзор

Ниже приведен код который принимает тип объекта (resources), берет несколько значений из этого объекта, а затем вычисляет расстояние и продолжительность из матрицы расстояний GoogleMaps. Результатом функции googleRequest() является обещание, содержащее два значения (расстояние и продолжительность).

Я хотел бы вернуть эти два значения обратно в for l oop, выполнить pushToRows(), а затем вернуть массив с именем final_rows.

Проблема

final_rows показывает НЕОПРЕДЕЛЕННО для ключей продолжительности и расстояния в каждой строке. Я предполагаю, что это происходит потому, что я пытаюсь получить доступ к значениям в dist_dur ненадлежащим образом. Буду признателен за любую помощь в решении этой проблемы. Спасибо.

Код

final_rows = []

    function getDistTime(resources){
        for (var i = 0; i < resources.data.length; i++) {
            var origin1 = $("#citystate").val();
            var destinationA = resources.data[i]['DEMOBILIZATION CITY'] + ',' + resources.data[i]['DEMOBILIZATION STATE'];
            var dist_time_data = googleRequest(origin1, destinationA).then((values) => {
                return values
            })
            pushToRows(resources.data[i], dist_time_data)
        }
        // console.log(final_rows)

    } 

    function pushToRows(resources, dist_dur){
        resources["DISTANCE_MI"] = dist_dur[0];
        resources["ACTUAL_DUR_HR"] = dist_dur[1];
        resources["FINANCE_DUR_HR"] = (dist_dur[0] / 45.0).toFixed(2)
        final_rows.push(resources)   
    }

Ответы [ 2 ]

1 голос
/ 14 июля 2020

Итак, что вам нужно сделать, это просто сохранить обещания в массиве в for l oop, а затем подождать, пока эти обещания разрешатся с помощью Promise.all, но это приведет к распараллеливанию ваших запросов на api расстояния Google.

    function getDistTime(resources){
        const promiseArr = [];
        for (var i = 0; i < resources.data.length; i++) {
            var origin1 = $("#citystate").val();
            var destinationA = resources.data[i]['DEMOBILIZATION CITY'] + ',' + resources.data[i]['DEMOBILIZATION STATE'];
            promiseArr.push(googleRequest(origin1, destinationA));
            
        }
        // Not sure how would you use the data pushed in rows but since you are not waiting for promises to be resolved, data would be updated later on 
        return Promise.all(promiseArr)
            .then((resultsArr) => {
                resultsArr.forEach((result, i) => pushToRows(resources.data[i], result));
            })

    } 

    function pushToRows(resources, dist_dur){
        resources["DISTANCE_MI"] = dist_dur[0];
        resources["ACTUAL_DUR_HR"] = dist_dur[1];
        resources["FINANCE_DUR_HR"] = (dist_dur[0] / 45.0).toFixed(2)
        final_rows.push(resources)   
    }

Я бы порекомендовал использовать asyn c -await, которые являются синтаксисом c сахаром для обещаний, но делают ваш код простым для понимания и устраняют сложности, связанные с цепочкой обещаний.

0 голосов
/ 14 июля 2020

Если вы переместите свой pushToRows() внутрь, где вы return values, у вас будет доступ к этим данным.

googleRequest(origin1, destinationA).then((values) => {
    pushToRows(resources.data[i], values);
});

Пока это обещание не будет выполнено, dist_time_data будет неопределенным

Вы также можете преобразовать в Promise.all(), который принимает массив обещаний и разрешается, когда все обещания выполнены:

function getDistTime(resources){
    const promises = [];

    for (var i = 0; i < resources.data.length; i++) {
        var origin1 = $("#citystate").val();
        var destinationA = resources.data[i]['DEMOBILIZATION CITY'] + ',' + resources.data[i]['DEMOBILIZATION STATE'];
        promises.push(googleRequest(origin1, destinationA));
    }

    return Promise.all(promises).then((results) => {
        return results.map((result, i) => {
            return {
                ...resources.data[i],
                DISTANCE_MI: result[0],
                ACTUAL_DUR_HR: result[1],
                FINANCE_DUR_HR: (result[0] / 45.0).toFixed(2)
            };
        });
    });
}

getDistTime(resources).then(result => {
    //result is now "final_rows"
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...