Estoy usando este paquete como contenedor de API para interactuar con la API de CampaignMonitor dentro de una función sin servidor. El objetivo es devolver una respuesta al llamador de la función serverless, confirmando si la operación de agregar un suscriptor a CampaignMonitor fue exitosa o no.
Esto es lo que tengo hasta ahora:
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' }), }; } }); };Desafortunadamente, esto no funciona, creo que debido a que no hay espera de la respuesta a la parte final donde se envía la solicitud. No estoy seguro de cómo manejarlo, ya que es una función de devolución de llamada.
He estado jugando con este código por un tiempo y, si no hay ningún error, el suscriptor se agrega a la lista de suscriptores y la función sin servidor devuelve una respuesta exitosa cuando la segunda declaración de devolución está fuera de la devolución de llamada ( debajo de api.subscribers.addSubscriber).
Problema
Devolver un valor de la función de devolución de llamada de api.subscribers.addSubscriber no lo convierte en un valor de retorno de la función del handler de contenedor.
Solución
Como la biblioteca que está utilizando no proporciona una API basada en promesas, puede crear un contenedor de promesas a su alrededor y usarlo para obtener el resultado deseado.
La forma más fácil de crear un envoltorio de promesa alrededor de algo en nodeJS es usar el módulo util incorporado.
const util = require("util"); const promisifedAddSubscriber = util.promisify(api.subscribers.addSubscriber); Una vez que tenga una función api.subscribers.addSubscriber basada en promesas, puede await la llamada a esta función.
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 }), }; } };Debe devolver una Promise de check_saved_url . Dentro de Promise, debe usar resolve para reemplazar return . También puede usar reject(new Error("error")) si hubo un error.
Puedes leer más sobre promesas en 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' }) }); } }); }); };encuentre la implementación funcional de async-await a continuación:
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 }), }; } };