Как вызвать один и тот же API несколько раз в Express Route?

Я работаю над приложением Node с Express. Я связываю несколько http-вызовов с API данных, каждый из которых зависит от ответов предыдущего запроса.

Все работает, кроме последнего звонка. Последний вызов должен произойти несколько раз, прежде чем страница должна отобразиться.

Поиск дал отличные примеры того, как связать, но не вызывать один и тот же API (или HTTP GET, конечную точку данных и т. д.) каждый раз с разными параметрами.

Я пытаюсь сделать что-то вроде этого: Использование генератора для многократного вызова API и разрешения только после завершения всех запросов?

var getJSON = (options, fn) => {
    .....
}

router.route("/")
    .get((req, res) => {
        var idArray = [];
        var results = [];
        getJSON({
            .... send params here, (result) => {

            //add response to results array
            results.push(result);

            //create var for data nodes containing needed id params for next call
            let group = result.groupsList;

            //get id key from each group, save to idArray
            for(i=0;i<groups.length;i++){
                idArray.push(groups[I].groupId);
            }

            //use id keys for params of next api call
            dataCallback(idArray);

        });  

        function dataCallback(myArray){
            // number of ID's in myArray determine how many times this API call must be made
            myArray.forEach(element => {
                getJSON({
                    .... send params here, (result) => {
                    results.push(result);
                }); 
            // put render in callback so it will render when resolved
            }, myRender());
        };

        function myRender() {
            res.render("index", { data: results, section: 'home'});
        }

    })

person Lisa Ziegler    schedule 05.02.2019    source источник


Ответы (1)


Я узнал проблему с приведенным выше кодом.

  1. Вы можете вызывать функции, которые находятся за пределами экспресс-маршрута, но не можете иметь их внутри маршрута.
  2. Вы не можете связать несколько вызовов, зависящих от данных, не в маршруте.

Все внутри route.get или route.post должно касаться данных, путей, рендеринга и т. д.

Это означает либо использование асинхронной библиотеки (которую я нашел бесполезной при попытке создать страницу из нескольких источников данных, с данными, зависящими от предыдущего ответа), либо наличие дополнительного файла js, который вы вызываете (с вашей веб-страницы), чтобы получить, обрабатывать и моделировать ваши данные, как здесь: -all-reques">Использование генератора для многократного вызова API и разрешения только после завершения всех запросов Вы также можете поместить его в свое приложение или индексный файл перед маршрутами.

(Сначала мне было непонятно, куда пойдет этот код. Я попытался поместить его в свой router.post. Несмотря на то, что документация говорит "Методы", мне не пришло в голову, что маршруты - это методы. Раньше я не делал ничего, кроме очень простых маршрутов, и никогда не заглядывал под капот. )

В итоге я остановился на третьем варианте. Я разбил различные вызовы API на своем экране, чтобы они вызывались только тогда, когда пользователь нажимает на что-то, что потребует больше данных, например, на аккордеон или переключатель вкладок.

Я использовал XMLHttpRequest() со своей веб-страницы для вызова собственного внешнего сервера Node, который затем вызывает сторонний API, после чего внешний сервер Node отвечает рендерингом моего файла мопса. используя данные, предоставленные API. Я получаю html обратно для своего экрана, чтобы добавить.

На странице:

callFEroutetoapi(_postdata, _route, function (_newdata){
                    putData(_newdata);
                });

function putData(tData){
            var _html = tData;
            var _target = document.getElementById('c-playersTab');
            applyHTML(_target, _html);
        }

function callFEroutetoapi(data, path, fn){
    //url is express route
    var url = path;
    var xhr = new XMLHttpRequest();

    console.log('data coming into xhr request: ', data);

    //xhr methods must be in this strange order or they don't run
    xhr.onload = function(oEvent) {
        if(xhr.readyState === xhr.DONE) {
            //if success then send to callback function
            if(xhr.status === 200) {
                fn(xhr.response);
                // ]console.log('server responded: ', xhr.response);
                }
            else {
                console.log("Something Died");
                console.log('xhr status: ', xhr.status);
            }
        }                
    }
    xhr.onerror = function (){console.log('There was an error.', xhr.status);}
    xhr.open("POST", url, true);
    xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
    xhr.send(JSON.stringify(data));
}

Он добавляет дополнительный слой, но был необходим для отображения последних, часто меняющихся данных. Его также можно использовать повторно, что лучше для многоэкранного веб-приложения. Если бы было меньше представлений (совершенно разные экраны и взаимозависимые наборы данных), более централизованный файл model.js, упомянутый выше, работал бы лучше.

person Lisa Ziegler    schedule 18.09.2019