Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Node.js and Express: How to return response after asynchronous operation

I'm new to Node.js, so I'm still wrapping my head around asynchronous functions and callbacks. My struggle now is how to return a response after reading data from a file in an asynchronous operation.

My understanding is that sending a response works like this (and this works for me):

app.get('/search', function (req, res) {
    res.send("request received");
});

However, now I want to read a file, perform some operations on the data, and then return the results in a response. If the operations I wanted to perform on the data were simple, I could do something like this -- perform them inline, and maintain access to the res object because it's still within scope.

app.get('/search', function (req, res) {
    fs.readFile("data.txt", function(err, data) {
        result = process(data.toString());
        res.send(result);
    });
});

However, the file operations I need to perform are long and complicated enough that I've separated them out into their own function in a separate file. As a result, my code looks more like this:

 app.get('/search', function (req, res) {
    searcher.do_search(res.query);
    // ??? Now what ???
});

I need to call res.send in order to send the result. However, I can't call it directly in the function above, because do_search completes asynchronously. And I can't call it in the callback to do_search because the res object isn't in scope there.

Can somebody help me understand the proper way to handle this in Node.js?

like image 435
ekl Avatar asked Apr 25 '16 10:04

ekl


People also ask

How do you return a response from an asynchronous call?

The A in Ajax stands for asynchronous. That means sending the request (or rather receiving the response) is taken out of the normal execution flow. In your example, $. ajax returns immediately and the next statement, return result; , is executed before the function you passed as success callback was even called.

How do you handle asynchronous response?

The best way to handle asynchronous API responses is to access the corresponding API resource (Rate or Transaction) one or multiple times after object creation. As soon as a carrier has returned a rate or label, it will be accessible in the corresponding Shippo API resource.

How do you return an array from async in NodeJS?

js ? We have to call the async function from another function which can be asynchronous or synchronous (We can pass the array or choose to declare the array in the async function itself) and then return the array from the async function.


2 Answers

To access a variable in a different function, when there isn't a shared scope, pass it as an argument.

You could just pass res and then access both query and send on the one variable within the function.


For the purposes of separation of concerns, you might be better off passing a callback instead.

Then do_search only needs to know about performing a query and then running a function. That makes it more generic (and thus reusable).

searcher.do_search(res.query, function (data) {
    res.send(...);
});

function do_search(query, callback) {
    callback(...);
} 
like image 142
Quentin Avatar answered Oct 18 '22 19:10

Quentin


The existing answers are perfectly valid, you can also use async/await keywords since ES2017. Using your own function:

app.get('/search', async(req, res, next) {
  try {
    const answer = await searcher.do_search(req.query);
    res.send(answer);
  }
  catch(error) {
    return next(error);
  }
});
like image 31
Echo C Avatar answered Oct 18 '22 18:10

Echo C