如何在Express Route中多次调用同一个api?

时间:2019-02-05 21:56:49

标签: loops express asynchronous router waterfall

我正在使用Express开发Node应用程序。我将几个http调用链接到数据api,每个调用均取决于前一个请求的响应。

除了最后一个电话,其他所有功能都可以使用。在页面呈现之前,最后一次调用需要进行多次。

搜索已成为一个很好的例子,说明如何链接而不是每次都使用不同的参数调用相同的API(或HTTP GET,数据终结点等)。

我在这里(Express | Making multiple http requests asynchronously)使用async.waterfall尝试了该方法,还尝试了async-kit。两者都不会前进到最终的回调,它们只会挂起。

下面的代码不使用异步。我退缩是因为我不确定最好的方法是什么。

我正在尝试执行以下操作:Using a generator to call an API multiple times and only resolve when all requests are finished?

那是最好的方法吗?我不想使用像async-kit这样的模块,因为一两年后它们往往会停止受到支持。虽然那会很棒。 任何帮助将不胜感激。

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'});
        }

    })

1 个答案:

答案 0 :(得分:0)

我了解了以上代码的问题。

  1. 您可以调用快速路线之外的函数,但不能将它们包含在路线之内。
  2. 您不能链接多个与数据相关的呼叫,而不是在路由中。

route.get route.post 中的所有内容都应与数据,路径,渲染等有关。

这意味着要么使用异步库(当尝试从多个数据源构建页面时,我发现它是无用的,其数据取决于先前的响应),或者具有一个要调用的附加js文件(从您的网页)要获得,处理和建模数据,例如:Using a generator to call an API multiple times and only resolve when all requests are finished,也可以在路由之前将其放入应用或索引文件中。

(起初我不知道代码的去向。我尝试将其放在router.post中。即使documentation表示“方法”,它也没有为我点击那条路线是方法。我之前做过的工作除基本路线之外,从来没有做过。)

我最终选择了第三个选项。我在屏幕上拆分了各种API调用,以便仅在用户单击需要更多数据的内容(例如手风琴或Tab开关)时才调用它们。

我从网页上使用了 XMLHttpRequest()来调用我自己的前端节点服务器,然后该前端服务器调用了第三方API,然后前端节点服务器以一个我的哈巴狗文件使用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));
}

它增加了一层,但是对于显示最新的,频繁更改的数据是必需的。它也可重用,这对于多屏Web应用程序更好。如果视图较少(完全不同的屏幕和相互依赖的数据集),则上面提到的更加集中的model.js文件会更好地工作。