Home > Software engineering >  NodeJS - return response as a process continue working anyways
NodeJS - return response as a process continue working anyways

Time:03-18

I have an async method which invokes a few calls (await promise....) in a loop, and eventually returns a result. When I get the result from that function, I send back a response to the client. What I have to do is to return a response in the middle of the process/loop, while the loop continue running. Of course it breaks the loop, since it returns from the function in the middle of the loop.

Here is a piece of code to demonstrate.

app.post('/test', async (req, res)=>{
    const body = JSON.stringify(req.body)
    await doSomething()
    res.status(200).send("ok");
});

const doSomething = async () => {
    let times = 0;
    for(let i=0 ; i<5 ; i  ){
        console.log(i)
        await delay(1000);
        if(i==2){
            return 2;
        }
    }
    return times;  
}

const delay = async (ms) => {
    return await new Promise(resolve => setTimeout(resolve, ms));
}

When I get i==2, I want to return a value and response to the client, but I still want the loop to run till the end. I thought to use some observer which will be responsible for returning a response, (say rxjs, event emitter, etc...). Not sure what is the best practice for such a different situation.

Thanks for any advice.

CodePudding user response:

The solution is to use a synchronous function and return a Promise. But AFAIK making the callback passed to the Promise constructor async won't work:

const doSomething = () => {
    let times = 0;
    return new Promise(async (resolveMain) => {
        for(let i=0 ; i<5 ; i  ){
            console.log(i)
            await delay(1000);
            if(i==2){
                resolveMain(2);
            }
        }
    });
}

It's also twisted LOL.

So I'm sure there are many other ways to accomplish this, but I'm assuming you want to keep the await delay(1000);. What you're gong to need is an async generator function.

app.post('/test', async (req, res)=>{
    const body = JSON.stringify(req.body)
    await doSomething()
    res.status(200).send("ok");
});

async function* doLoopyThing(){
    let times = 0;
    for(let i=0 ; i<5 ; i  ){
        console.log(i)
        await delay(1000);
        if(i==2){
            yield 2;
        }
    }      
}

function doSomething(){
    return new Promise(resolve => {
        const looper = doLoopyThing();
        looper.next().then(({value}) => resolve(value));
        looper.next();
    }
}

This is also twisted, but it should work.

I don't understand how this can possibly be the right way to actually accomplish something. But I'm assuming the is just for fun, or you're trying to learn.

Also if all you were trying to show with the await delay(1000) was a heavy function, and you don't actually need the function to be asynchronous, the first solution should work.

  • Related