Home > Blockchain >  How do I return a value for a non promise callback inside an async fucntion
How do I return a value for a non promise callback inside an async fucntion

Time:08-19

In below Node.js function, how do I return data.QueueUrl, so that a caller can get the value with

var url = await createSubscription('foo', req);

This is the function

async function createSubscription(name, req){
  var params = {
    QueueName: name,
    Attributes: {
        'ReceiveMessageWaitTimeSeconds': '20', // long polling wait time
    }
  };
  sqs.createQueue(params, function(err, data) {
    if (err) {
      logger.error("createQueue error : "   err, req);
    } else {
      logger.log("queue "   name   ' created', req);
      return data.QueueUrl;
    }
  });
}

CodePudding user response:

You could make your function to return a Promise and resolve and reject the required data according to your logic. The other way is to promisfy your callback using the util module.

CodePudding user response:

Write your function like this to return a promise

async function createSubscription(name, req){
    try{
        const params = {
          QueueName: name,
          Attributes: {
              'ReceiveMessageWaitTimeSeconds': '20', // long polling wait time
          }
        };

        let data = await sqs.createQueue(params).promise();
        return data;
    }
    catch(err){
        logger.error("createQueue error : "   err.message);
    }
}

And call it like this to receive the value

const url = await createSubscription('foo', req);
console.log(url.QueueUrl); // You'll get the result in url variable.

CodePudding user response:

The function doesn't need to be async to create and return a promise:

function createSubscription (name, req) {
  return new Promise((resolve, reject) => {
    const params = {
      QueueName: name,
      Attributes: {'ReceiveMessageWaitTimeSeconds': '20'}
    };
  
    sqs.createQueue(params, (err, data) => {
      if (err) {
        logger.error('createQueue error : '   err, req);
        reject(err);
      } else {
        logger.log('queue '   name   ' created', req);
        resolve(data.QueueUrl);
      }
    });
  });
}

const url = await createSubscription('foo', req);

CodePudding user response:

Best practice is to wrap problematic functions at the lowest possible level, and then never call them directly again - MDN

For you this means doing the following:

function createQueue(params) {
  return new Promise((resolve, reject) => {
    sqs.createQueue(params, (err, data) => err ? reject(err) : resolve(data));
  });
}

After that you can work with createQueue instead of sqs.createQueue:

async function createSubscription(name, req) {
  const params = {
    QueueName: name,
    Attributes: {
        'ReceiveMessageWaitTimeSeconds': '20', // long polling wait time
    }
  };

  try {
    const data = await createQueue(params);
    logger.log("queue "   name   ' created', req);
    return data.QueueUrl;
  } catch (err) {
    logger.error("createQueue error : "   err, req);
    // you'll probably want to re-throw here unless the caller knows
    // that an undefined return value means an error has occurred
  }
}

Without all the additional log statements, the function can also look like this:

async function createSubscription(name, req) {
  const params = {
    QueueName: name,
    Attributes: {
        'ReceiveMessageWaitTimeSeconds': '20', // long polling wait time
    }
  };

  const data = await createQueue(params);
  return data.QueueUrl;
}

Since we don't use a try/catch the error/rejected promise bubbles up to the caller.


Since all the SQS functions are in the style sqs.function(params, callback) (see documentation), you could also write a more general helper that works on all the SQS functions.

function sqsPromise(sqsFnName, params) {
  return new Promise((resolve, reject) => {
    sqs[sqsFnName](params, (err, data) => err ? reject(err) : resolve(data));
  });
}

Which allows you to do:

const data = await sqsPromise("createQueue", params);
  • Related