0

I'm writing an API that receives a request & then runs a fairly complex function on Puppeteer however I don't want the API to wait for the function to finish executing before throwing a success response as it's only a submit API?

Here's the current flow:

const createOrder = async (req, res) => {
    try {

        console.log(req.body);

        let params = await parser.parseStringPromise(req.body.parameters);

        device_imei = params.PARAMETERS.IMEI;

        //config
        axios.defaults.withCredentials = true;
        axios.defaults.timeout = 15000;
        userProfile = faker.entity.user();

        recaptcha_solution = await get_captcha_solution();

        page = await browser.newPage();

        page.on('response', handle_response);

        await page.goto('https://www.website.com', {
            waitUntil: 'networkidle0',
        });

        //etc......

    } catch (error) {

        if(page) {
            await page.close();
        }

        return res.send(error_response(error.message));

    }
});

app.post('/api/index.php', async function (req, res) {
    switch(req.body.action) {
        case "placeimeiorder":
            return await createOrder(req, res);
        default:
            return res.send(error_response('Invalid Action'));
    }
});

How could I have it just execute the function & then return a instant JSON response while the script runs in the background?

Curtis
  • 2,646
  • 6
  • 29
  • 53
  • 3
    Just put your `res.send()` wherever you want it to be. It can be the first line of your function if you want and that will send the response immediately without waiting for anything else to execute. You will, of course, give up your ability to communicate back anything about an error in the operation if you do that since you will have already sent the response when you discover you have an error. – jfriend00 Jun 30 '20 at 13:43
  • Have a look at [Can I fire and forget a promise in nodejs?](https://stackoverflow.com/q/32384449/1048572) – Bergi Jun 30 '20 at 14:07

1 Answers1

1

In an async function, await waits for a promise to settle before allowing the function logic to continue. If you don't want to wait for a promise to settle, don't use await on it.

So for instance, if the operation you want to start but not wait for is the page.goto call, remove the await in front of it. You might also add a rejection handler via .catch so you can handle and report any error it returns (asynchronously, after your function has returned):

//  v−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− no `await`
    page.goto('https://www.website.com', {
        waitUntil: 'networkidle0',
    })
    .catch(error => {
        // Handle/report the fact an error occurred; at this point, your
        // `createOrder` call has already finished and sent the response, so
        // you can't send an error response but you can use the information
        // in some other way
    });
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • It's not functions inside the `createOrder` I'm concerned about, it's the whole `createOrder` I want to execute in the background once the Express Route gets a request & then just return a JSON response instantly. – Curtis Jun 30 '20 at 13:54
  • 2
    @Curtis - It's the same answer, though: If you don't want to wait for it, don't use `await` when calling `createOrder`. – T.J. Crowder Jun 30 '20 at 14:01