javascriptnode.jsasync-awaitnode-fetch

Using async-await with node-fetch does not return the response to the calling method


I have a function defined in a module that is supposed to do a fetch and return the response. I am having trouble returning the response from the fetch. The calling function gets the return value as "undefined".

I am new to JavaScript and Node so might need a little bit of hand-holding if you don't mind.

Calling function

async function executeTest() {
    try {
        const response = await bpc.postLendingApplication(
            blendConnection,
            loanData
        );
        console.log("Response from POST Loan: ", response);
    } catch (error) {
        console.log(error);
    }
}

Module function doing the fetch request

const fetch = require("node-fetch");
async function postLendingApplication(connection, data) {
    console.log("Processing POST Loan.");
    await fetch(connection.url, {
        method: "POST",
        headers: connection.headers,
        body: data,
    }).then(async res => {
        console.log("Status: ", res.status);
        console.log("StatusText: ", res.statusText);
        console.log("OK: ", res.ok);
        return await res;
    });
}

The console output is:

Processing POST Loan.
Status:  200
StatusText:  OK
OK:  true
Response from POST Loan:  undefined

As you can see, the fetch did what it was supposed to do and if I log the res.json() within the module method, it prints the payload. But I would like to return the error and response from the fetch so the module behaves as a generic method and the processing and error handling is done in the calling method.


Solution

  • When you mark a function as async, JavaScript will always return a Promise, thus making it asynchronous. When you return a value, it is resolving the Promise. Using await inside of these functions "pauses" execution (it is technically creating a new function for code that occurs after the await) until the awaited Promise is resolved, standing in place of the usage of then(callback). As such, you don't need then inside of any async function.

    You do, however, need to treat your own async function as a Promise.

    const fetch = require("node-fetch");
    async function postLendingApplication(connection, data) {
        try {
          console.log("Processing POST Loan.");
    
          // the await eliminates the need for .then
          const res = await fetch(connection.url, {
              method: "POST",
              headers: connection.headers,
              body: data,
          })
          // this code is resumed once the fetch Promise is resolved.
          // res now has a value.
          console.log("Status: ", res.status);
          console.log("StatusText: ", res.statusText);
          return res;
       }
       catch(err) { 
         // because the promise could error, it is advised to use
         // try/catch. With a Promise, you would .then(cb).catch(errHandler)
         // but async/await doesn't utilize callbacks.
    
         // perform error handling or you can bubble it up.
        throw err
    }
    

    When calling postLendingApplication(connection, data) make sure that you are either using await, if inside an async function or postLendingApplication(connection, data).then(callback) as the return value will be a Promise.

    postLendingApplication(connection, data).then(callback).catch(errHandler)