简体   繁体   中英

How to speed up a function call in nodejs

I'm creating a get request to the backend as soon certain data is posted to the database. So in other to wait for the post request to be completed before a get request is fired, I implemented a waiting logic like so, postArray.called = true

const postArray = async (arr) => {
    const movie = {
        name: searchTerm,
        result: arr
    }
    try {
        await axios({
            method: 'post',
            url: url,
            data: result,
            headers:{
                "Content-Type":"application/json",
                "Accept":"application/json"
              }
            })
    } catch (error) {
        console.log(error)
    }
    postArray.called = true
}

To make the get request wait for the post request, I used a if condition like so.

app.get("/getNewList", (req, res)=>{
    if(postArray.called){
        process.nextTick(()=>{
            axios.get('http://localhost:3001/List')
                .then(response => res.send(response.data))
                .catch(error => res.send(error))
        })
    }
})

The problem is, this get request doesn't get call for another 2 or 3 minutes after the post request has been called. I need a way to speed up this function call so it doesn't slow my app down completely.

Sometimes, the request times out and I get a timeout error.

Is there another way to make this quicker?

////EDIT////

I have been informed that using if(postArray.called) is not the same as making the get request wait, so I tried something else.

 async function getData(props){
        let Result = []
        let fetchAgain = await axios.get('/getNewList')
        Result = fetchAgain.data.find(x => x.name.toLowerCase() === props.toLowerCase()).result
        showResult(Result)
    }

 async function fetchPost(props){
      axios.post(`/${props}`)
        .then((res) =>{
            if(res.status === 200){
                getData(props)
            }
        }) 
    }

This is the new request made from the front end. I declared a function to call the get request, then passed it to the .then part of the post request. this still doesn't work. Keep in mind that if(postArray.called) was removed from the get request on the backend


The fetchPost function was used to send data to my backend which then queries two external APIs:

function newFetch(a){
    const promises = [
  Fetch(`https://externalapi1?=${a}.com`,
  Fetch(`https://externalapi2?=${a}.com`,]
    
    Promise.all(promises)
        .then(values =>{
            const result = values.filter(o=>Object.values(o).every(v=>v) && Object.entries(o).length);

            postArray(result)}
        .catch(err => console.log(err))
}

This is where the postArray function is called. Then I intend to fetch this data from the backend to render to my client. Using both failed methods listed above

///End EDIT///

/////This is the place where newFetch was called////

app.post("/:endpoint([\\/\\w\\ ]*)", async (req, res) =>{
    newFetchPromise = await newFetch(req.params.endpoint).catch(err => {
        newFetchPromise = null
    })
})

Assuming this is a per-server operation, not a per-user operation...

First, fix newFetch() so that it returns a promise that is tied to when postArray() is done:

function newFetch(a) {
    const promises = [
        Fetch(`https://externalapi1?=${a}.com`),
        Fetch(`https://externalapi2?=${a}.com`),
    ];
    return Promise.all(promises).then(values => {
        const result = values.filter(o => Object.values(o).every(v => v) && Object.entries(o).length);
        return postArray(result);
    }).catch(err => {
        // log and rethrow so caller sees the error
        console.log(err);
        throw err;
    });
}

Then, wherever you call newFetch() , you need to save the returned promise into a module-level variable:

 // module level variable
 let newFetchPromise;


 // wherever you call newFetch()
 newFetchPromise = newFetch(...).catch(err => {
     newFetchPromise = null;
 });

Then, in your route handler, you can wait for that module-level promise:

app.get("/getNewList", (req, res)=>{
    if (newFetchPromise) {
        // wait for newFetchPromise
        // this will work whether newFetchPromise has already finished or is still
        // processing
        newFetchPromise.then(() => {
            return axios.get('http://localhost:3001/List');
        }).then(response => {
            res.send(response.data);
        }).catch(err => {
            // maybe want to set an error status here?
            res.send(err);
        });
    } else {
        // have to send some sort of response here if there was no newFetchPromise
        console.log("no newFetchPromise to wait for");
        res.sendStatus(500);
    }
});

As newFetch() is called again, it will just update the module-level newFetchPromise to the latest one so any new /getNewList requests will always wait for the latest promise while any prior ones will wait for the same one they originally waited for.

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