Как мне получить доступ к обещанию в массиве ответов? - PullRequest
2 голосов
/ 23 марта 2020

В настоящее время у меня возникают проблемы при первом использовании Promise.all () (два метода get). В настоящее время, когда я консоль записываю в журнал свой ответ, я вижу данные, которые я пытаюсь получить из-под обещания в ответе. Но я не уверен, как получить к нему доступ?

Вот мой код:

getData: function () {
            Promise.all([
                fetch('@Url.Action("GetSomething")',
                    {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json'
                        },
                        body: JSON.stringify(this.selectedValues)
                    }),
                fetch('@Url.Action("GetSomethingElse")',
                    {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json'
                        },
                        body: JSON.stringify(this.selectedValues)
                    })
            ]).then(responses => {
                if (responses[0].ok && responses[1].ok) {
                    return responses.map(response => {
                        return response.json(); 
                    });
                } else {
                    throw new Error(`Error ${response.status}`);
                }
            }).then(responseArray => {
                console.log("LOG: ", responseArray);

            }).catch(error => {
                console.log(error);
            });
        },

Почитав онлайн ответы, есть несколько предложений по добавлению еще одного .then (), который дал мне тот же результат (два обещания). Я посмотрел на связанные вопросы по этой проблеме здесь, в StackOverflow, но только запутался. Я также попытался сделать следующее, что также дало те же результаты:

...
}).then(responseArray => {

    console.log("LOG: ", responseArray);
    Promise.resolve([responseArray[0], responseArray[1]]).then((results) => {
        console.log("Resolved results: ", results);
    });

}).catch(error => {
    console.log(error);

});

Я сейчас застрял! Вот что console.log показывает в ответе:

LOG: (2) [Promise, Promise]
   >0: Promise: {<Resolved>: (Array(20)}
   >1: Promise: {<Resolved>: (Array(10)}

Помощь очень ценится, и я надеюсь, что есть небольшая деталь, которую мне не хватает. Как я могу получить доступ к этим обещаниям? Спасибо!

Ответы [ 2 ]

2 голосов
/ 23 марта 2020

Вы не ожидали обещаний, которые вернет res.json(). Вы можете добавить еще Promise.all() к результату вашего .map() или можете просто вставить их в первоначальное обещание, которое вы используете Promise.all(). Последнее - моя рекомендация:

function fetchJSON(...args) {
    return fetch(...args).then(response => {
        if (!response.ok) {
            throw new Error(`Error ${response.status}`);
        }
        return response.json();
    });
}

getData: function() {
    Promise.all([
        fetchJSON('@Url.Action("GetSomething")', {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify(this.selectedValues)
        }),
        fetchJSON('@Url.Action("GetSomethingElse")', {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify(this.selectedValues)
        })
    ]).then(responseArray => {
        console.log("LOG: ", responseArray);
        // use responseArray here
    }).catch(error => {
        console.log(error);
    });
},

К вашему сведению, я регулярно нахожу, что получение ответов с использованием fetch() неоправданно многословно и, таким образом, заканчивается использованием некоторой вспомогательной функции, такой как fetchJSON(), которую я использовал здесь чтобы не повторять код.


На мой взгляд, интерфейс fetch() должен был предложить две вещи.

  1. Опция, позволяющая вам сказать, что вы этого хотели отклонить, если не статус 2xx. Я понимаю вариант использования для не всегда отклонения в этом случае, но, вероятно, есть и другие варианты использования, в которых вы хотите, чтобы он отклонил, поэтому это должен был быть вариант.
  2. Параметр, чтобы сказать ему прочитать ответ и вернитесь в виде текста, json или другого типа, чтобы вам не пришлось делать еще одно обещание, возвращающее вызов функции, чтобы сделать это.

FYI, модуль request-promise для nodejs , имеет обе эти опции (потому что они регулярно нужны).

Но, поскольку у них нет этих опций (хотя они регулярно нужны), нам иногда приходится переносить их, чтобы добавить эти опции, чтобы избежать повторения код. В этом случае вы хотите, чтобы он отклонял, если не статус 2xx, и вы хотите, чтобы он считывал и анализировал JSON, и вы хотите сделать это в двух местах, поэтому мы делаем небольшую служебную функцию, которая делает именно это.

1 голос
/ 23 марта 2020

Возвращение обещания в then обратном вызове приводит к выполнению обещания в следующем then в цепочке.

Однако здесь возвращается массив обещаний, обещания не разрешаются в следующем then :

return responses.map(response => {
    return response.json(); 
});

Должен быть либо другой Promise.all для их параллельного разрешения:

return Promise.all(responses.map(response => {
    return response.json(); 
}));

, либо он может быть переписан для последовательной обработки с for l oop, потому что после выполнения запросов заметных улучшений от параллелизма не ожидается.

В любом случае, async..await делает это более простым:

async getData() {
    try {
        const responses = await Promise.all([
            fetch(...),
            fetch(...)
        ]);

        const responseArray = [];
        for (const response of responses) {              
            if (!response.ok)
                throw new Error(`Error ${response.status}`);

            responseArray.push(await response.json());
        }
        ...
    } catch (error){
        console.log(error);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...