简体   繁体   中英

Save data from http request into an array, to send it as json back to the client

I have a node.js server that does an API request, the page should send as response the data I get from that api. The catch here is:

I need to do several calls to the api, put all the data together separated by an id e send that back as json to the client.

To create that request I have first to query my DB and get the data I have to send to the api After that I filter that data using array.filter and to create the requests, I am using array.map to call a function that deals with the request.

Code:

router.get('/', cors(),  (req, res) =>{

    const response =  getListOfStatistics()
 });

when I enter the page, the function getListOfStatistics() is fired:

function getListOfStatistics(){
    axios.get('http://localhost:4002/')
    .then(response =>{
        items = response.data
        let result = filterStatistic(items)
        return result;
        //I wrote that return result when trying to give the data back
        //So I could send it to the client as json

    })
    .catch(err =>{
        console.log(err)
    })    

}

After getting the data from the db, I try filtering it:

function filterStatistic(items){

const jahreStatistic = items.filter(item => item.period == 0)
const virtelJahrStatistic = items.filter(item => item.period == 3)

//Both methods above are working

jahreStatistic.map(item => {
    connection.statistic_id = item.statistic_id
    var periods = getReportingPeriod(item.period)
    for(let i=0; i < 3; i++){
        switch(i){
            case 0:
            connection.reporting_period = periods.prevYear
            preOrderedObjects.Jahr =  sendHTTPRequest(item)
            break;
            case 1:
            connection.reporting_period = periods.actualYear
            preOrderedObjects.Jahr =   sendHTTPRequest(item)
            break;
            case 2:
            connection.reporting_period = periods.nextYear
            preOrderedObjects.Jahr =   sendHTTPRequest(item)
            break;
         }
        }
    })
}


function  sendHTTPRequest (item){

request.post({
    headers: {'content-type' : 'application/x-www-form-urlencoded'},
    url: 'https://externalapi/api/', 
    form: connection
    },
    (err, response, body) => {
        if(response.headers['x-status'])
        {
            info.name = item.name
            info.evas = item.evas
            info.id = item.statistic_id
            info.link = item.link
            info.resourceID = response.headers['x-resourceid'];
            info.fileName = response.headers['x-filename'];

            console.log(info.name) //This shows that my three requests 
            were made.

            **if(item.period==0){
                //Evas is a global array evas = []
                //info is a global object info = {}
                evas.push(info)
                //My goal was to push each request to this array and 
                //return it to after, add to another object.
                //This does not work.
                return evas**
            }else{
                ids.push(info)
                preOrderedObjects.Jahr = ids
            }
            }
    }) 
}

I would like to get all the data pushed to the evas array and then added to my preOrderedObjects.Jahr

After, at the end, I want to return that to the client as json

Anyone has an idea of what I am missing and how to maybe fix that?

You need to convert your getListOfStatistics function into a callback function . You are making a GET request to another server using promises (we can say a better version of callbacks) and the result might take a while to have a value.

The callback will return the result variable once it has a value.

function getListOfStatistics(callback){
    axios.get('http://localhost:4002/')
    .then(response =>{
        items = response.data
        let result = filterStatistic(items)
        callback(result);
    })
    .catch(err =>{
        console.log(err)
    })
}

To execute getListOfStatistics , you will need to pass a function as a parameter, like this:

let response;
getListOfStatistics(function(result)){
    response = result;
}

Note that response must be a variable and it will have a value once the callback is finished.

Same goes for sendHTTPRequest method, you will need to convert it too since you want all requests to finish. However using Evas and preOrderedObjects as global variables don't look like a good idea, but anyways.

function filterStatistic(items, callback){

const jahreStatistic = items.filter(item => item.period == 0)
const virtelJahrStatistic = items.filter(item => item.period == 3)

//Both methods above are working

jahreStatistic.map(item => {
    connection.statistic_id = item.statistic_id
    var periods = getReportingPeriod(item.period)
    for(let i=0; i < 3; i++){
        switch(i){
            case 0:
            connection.reporting_period = periods.prevYear
            sendHTTPRequest(item, function(result){
              preOrderedObjects.Jahr =  result
            })
            break;
            case 1:
            connection.reporting_period = periods.actualYear
            sendHTTPRequest(item, function(result){
              preOrderedObjects.Jahr =  result
            })
            break;
            case 2:
            connection.reporting_period = periods.nextYear
            sendHTTPRequest(item, function(result){
              preOrderedObjects.Jahr =  result
            })
            break;
         }
        }
    })
}


function  sendHTTPRequest (item, callback){

request.post({
        headers: {'content-type' : 'application/x-www-form-urlencoded'},
        url: 'https://externalapi/api/', 
        form: connection
    },
    (err, response, body) => {
        if(response.headers['x-status'])
        {
            info.name = item.name
            info.evas = item.evas
            info.id = item.statistic_id
            info.link = item.link
            info.resourceID = response.headers['x-resourceid'];
            info.fileName = response.headers['x-filename'];

            console.log(info.name) //This shows that my three requests 
            were made.

            **if(item.period==0){
                evas.push(info)                
                callback(evas)
            }else{
                ids.push(info)
                preOrderedObjects.Jahr = ids
            }
         }
    }) 
}

Well, for starters you can try to change the request headers to: 'application/json'.

As for the requests, they are async, so you cannot get the result immediately, you can turn the getListOfStatistics into a callback or call the async/await trick on the function as follows:

function getListOfStatistics(){
    axios.get('http://localhost:4002/')
    .then(async (response) =>{
        items = response.data
        let result = await filterStatistic(items);

        return result;
    })
    .catch(err =>{
        console.log(err)
    });

As for that switch/case, you are also making http async requests, you can use the async await method OR you can push the requests into a promise array and resolve them all at once:

let requests = [];

jahreStatistic.map(item => {
    connection.statistic_id = item.statistic_id
    var periods = getReportingPeriod(item.period)
    for(let i=0; i < 3; i++){
        switch(i){
            case 0:
            connection.reporting_period = periods.prevYear
            requests.push(sendHTTPRequest(item));
            break;
            case 1:
            connection.reporting_period = periods.actualYear
            requests.push(sendHTTPRequest(item));
            break;
            case 2:
            connection.reporting_period = periods.nextYear
            requests.push(sendHTTPRequest(item));
            break;
         }
        }
    })
}

Promise.all(requests).then((results) => {
 // do some work here
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM