javascriptes6-promisenetlifymailchimp-api-v3.0netlify-function

Returning Promises from Netlify Function


I am working on a serverless function to be hosted on Netlify to subscribe users to a mailchimp email list.

I am getting the following obscure error:

lambda response was undefined. check your function code again

Here is my function:


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

        mailchimp.setConfig({
            apiKey: 'XXXXXXXXX',
            server: 'us20',
        });

        const submit = async () => {
            const response = await mailchimp.lists.addListMember("XXXXXXXX", {
                email_address: body.email.toLowerCase(),
                status: 'subscribed'
            });

            if (response.errors !== undefined && response.errors.length) { 
                throw new Error(response.errors);
            }
        }

        submit().then(response => {
            console.log(response);

            return {
                statusCode: 200,
                body: JSON.stringify({ response }),
            }
        }).catch(errors => {
            return {
                statusCode: 500,
                body: JSON.stringify({ errors }),
            }
        });
    } catch (error) {
        // output to netlify function log
        console.log(error);

        return {
            statusCode: 500,
            // Could be a custom message or object i.e. JSON.stringify(err)
            body: JSON.stringify({ msg: error.message }),
        }
    }
}

module.exports = { handler }

I think the issue may be because nothing is being returned after calling submit(), but I am not sure how best to return it. I still can't quite get my head around promises.

I am really hoping someone can point me in the right direction.

Many thanks David


Solution

  • You are on the right track, nothing is returned in the submit function so the response will always be undefined. Also You are using .then with async/await syntax which is ok, async/await is just a cleaner way of using promises so you typically use one or the other. And nesting catch blocks here is unnecessary. I would rewrite it to something like this:

    const handler = async function (event, context) {
      try {
          let body = JSON.parse(event.body);
    
          mailchimp.setConfig({
              apiKey: 'XXXXXXXXX',
              server: 'us20',
          });
    
          const submit = async () => {
            const response = await mailchimp.lists.addListMember("XXXXXXXX", {
                email_address: body.email.toLowerCase(),
                status: 'subscribed'
            });
            if (response.errors !== undefined && response.errors.length) {
                throw new Error(response.errors);
            }
            return response;
          }
    
          const response = await submit();
          return {
            statusCode: 200,
            body: JSON.stringify({ response }),
          }
      } catch (error) {
          // output to netlify function log
          console.log(error);
    
          return {
              statusCode: 500,
              // Could be a custom message or object i.e. JSON.stringify(err)
              body: JSON.stringify({ msg: error.message }),
          }
      }
    }

    If you are still struggling with promises, Id recommend reading the docs for them as well as the docs for async/await.

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function