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 }),
};
}
};