Home > Net >  How do I deal with async for a response in a callback function?
How do I deal with async for a response in a callback function?

Time:09-30

I'm using this package as an API wrapper to interact with the CampaignMonitor API within a serverless function. The objective is to return a response to the caller of the serverless function, confirming whether the operation of adding a subscriber to CampaignMonitor was successful or not.

Here is what I have so far:

exports.handler = async (event, context) => {
  const body = JSON.parse(event.body);

  // set request details
  const listId = process.env.CM_LIST_ID;
  const details = body;

  // Send Request and check for error returned
  api.subscribers.addSubscriber(listId, details, (err, res) => {
    if (err) {
      return {
        statusCode: 400,
        body: JSON.stringify({ message: err }),
      };
    } else {
      return {
        statusCode: 200,
        body: JSON.stringify({ message: 'success' }),
      };
    }
  });
};

Unfortunately, this doesn't work, I think due to the fact that there is no await for the response to the final part where the request is sent. I'm a little unsure of how to handle it, with it being a callback function.

I've been playing with this code for a little while now and, if there is no error, the subscriber is added to the subscriber list and a success response is returned from the serverless function when the second return statement is outside of the callback (below api.subscribers.addSubscriber).

CodePudding user response:

find working implementation of async-await below:

exports.handler = async (event, context) => {
  try
  {
      const body = JSON.parse(event.body);

      // set request details
      const listId = process.env.CM_LIST_ID;
      const details = body;
    
      const result = await api.subscribers.addSubscriber(listId, details);
      return {
        statusCode: 200,
        body: JSON.stringify({ message: 'success' }),
      };
  }
  catch(err){
      return {
      statusCode: 400,
      body: JSON.stringify({ message: err }),
    };
  }
};

CodePudding user response:

You need to return a Promise from check_saved_url. Inside of the Promise, you then need to use resolve to replace return. You can also use reject(new Error("error")) if there was an error.

You can read more about promises on MDN

exports.handler = async(event, context) => {
    return new Promise((resolve, reject) => {
        const body = JSON.parse(event.body);

        // set request details
        const listId = process.env.CM_LIST_ID;
        const details = body;

        // Send Request and check for error returned
        api.subscribers.addSubscriber(listId, details, (err, res) => {
            if (err) {
              reject(new Error({
                  statusCode: 400,
                  body: JSON.stringify({
                    message: err
                  })
                }));
              } else {
                resolve({
                  statusCode: 200,
                  body: JSON.stringify({
                    message: 'success'
                  })
                });
              }
            });
        });
    };

CodePudding user response:

Problem

Returning a value from the callback function of api.subscribers.addSubscriber doesn't make it a return value of the wrapper handler function.

Solution

As the library you are using doesn't provide a promise-based API, you can create a promise wrapper around it and use that to get the desired result.

Easiest way to create a promise wrapper around something in nodeJS is to use the built-in util module.

const util = require("util");

const promisifedAddSubscriber = util.promisify(api.subscribers.addSubscriber);

Once you have a promise-based api.subscribers.addSubscriber function, you can await the call to this function.

exports.handler = async (event, context) => {
  try {
    ...

    // explicitly bind "this"
    const result = await promisifedAddSubscriber.bind(api.subscribers)(listId, details);
  
    return {
      statusCode: 200,
      body: JSON.stringify({ message: 'success' }),
    };
  }
  catch (error) {
    return {
      statusCode: 400,
      body: JSON.stringify({ message: error }),
    };
  }
};
  • Related