Как выполнить несколько аксиос, получить запросы на основе динамически создаваемого массива запросов - PullRequest
0 голосов
/ 02 июня 2019

Я пытаюсь выучить Angular / node & express. В настоящее время я пытаюсь написать конечную точку для моей резервной копии,

  1. Необходимо использовать axios для запуска запроса на получение внешнего API, который вернет список идентификаторов (чисел)
  2. Для каждого из предоставленных идентификаторов запустите запрос, который получает сведения на основе этого идентификатора.

Но мой вопрос касается номер 2 . У меня есть список идентификаторов в качестве входных данных, и я хотел бы выполнить запрос к внешнему API (используя axios) на основе каждого из этих идентификаторов. Может быть полезно заметить - запрос к внешнему API на основе идентификатора возвращает объект с деталями этого идентификатора, поэтому моя общая цель с этой конечной точкой моего API - вернуть массив объектов, где каждый объект содержит детали идентификаторы.

Была пара вопросов, похожих на мои ...

  1. Загрузка ответов на запрос axios в массив (Это очень похоже на мой вопрос)
  2. Axios случайное количество запросов

Однако они используют React.js, и у меня возникают трудности с адаптацией их решения для узла / экспресса.

Я пытаюсь смоделировать свой подход на основе фрагмента кода, приведенного в верхней части первого вопроса. Но мое решение - вернуть пустой объект в качестве ответа.

Мой вопрос: что я могу сделать по-разному, чтобы сделать несколько аксиос GET-запросов на внешний API, где каждый запрос создается динамически

app.route('/test').get((req, res) => {
    axios
        .get('https://www.thecocktaildb.com/api/json/v1/1/filter.php?i=vodka')//This will not be hardcoded, but grabbed as a parameter from the endpoint
        .then(function(response) {
            //Purpose of this initial .then() clause is to make a call to the cocktaildb API to get the IDs of all the cocktails with a given ingredient eg: vodka.

            var data = response.data;//response.data contains the JSON object containing the contents received by the cocktaildb API request.
            var cocktailIds = [];

            //collect all cocktail ids so we can later make more requests to obtain the details associated with that ID.
            data.drinks.forEach(drink => {
                cocktailIds.push(drink['idDrink']);
            });

            //this is passed on to the next then clause. It is a list of cocktail ids.
            return cocktailIds;
        })
        .then((drinks) => {
            //the promises variable contains a list of all the requests we will have to make in order to get the details of all cocktail ids. I have tested that they are valid requests.
            const promises = drinks.map(id => {
                //console.log(getCocktailDetailsUrl + id);
                return axios.get(getCocktailDetailsUrl + id)
                .then(({data}) => {
                    return data;
                })
            })
            
            //I was hoping Promise.All to execute all of the requests in the promise and response to be stored in the cocktailDetails variable
            const cocktailDetails = Promise.all(promises)
            .then(values => {
                return values;
            })
            .catch(error => {
                console.log("There was an error when sending requests for details of all cocktails");
                console.log(error);
            })

            //Sending response only formatted this way for testing purposes
            if(cocktailDetails) {
                //this block is executed, and an empty object is returned as response
                console.log("cocktails was sent as response");
                res.send(cocktailDetails);
            } else {
                console.log("cocktails was not sent as response");
                res.send("cocktailDetails was not poppulated at the time of sending response");
            }
        })
        .catch(function (error) {
            res.send("There was an iswsue with your request to the cocktaildb API.");
            console.log('The following is the error from the request to the cocktaildb API: ' + error);
        })
});

Как я упоминал ранее, мой ответ содержит пустой объект. Я знаю, что должен каким-то образом использовать promise.all, но я не уверен, как правильно его реализовать.

Ответы [ 2 ]

0 голосов
/ 02 июня 2019

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

app.route('/test').get((req, res) => {
    axios.get('https://www.thecocktaildb.com/api/json/v1/1/filter.php?i=vodka')//This will not be hardcoded, but grabbed as a parameter from the endpoint
    .then(function(response) {

        const promises = response.data.drinks.map(drink =>axios.get(getCocktailDetailsUrl + drink.idDrink).then(({data})=>data));

        //I was hoping Promise.All to execute all of the requests in the promise and response to be stored in the cocktailDetails variable
        return Promise.all(promises)
        .then(values => {
            res.send(values);// shouldn't you be using res.json() here?
        });//if an error is thrown for any reason here, it will be caught by your outer catch 
    })
    .catch(function (error) {
        res.send("There was an iswsue with your request to the cocktaildb API.");
        console.log('The following is the error from the request to the cocktaildb API: ' + error);
    });
});
0 голосов
/ 02 июня 2019

Вы должны дождаться обещания, прежде чем пытаться отправить ответ.

Добавьте await до Promise.all, и вам не нужен блок then

const cocktailDetails = await Promise.all(promises)
...