0

I am trying to do something that I just can't wrap my head around, I have tried doing something with promises but still get stuck. I tried reading through this and still am stuck How do I return the response from an asynchronous call?

What I need to do is run the following code and get the body outside of the req, so I can check if it is succesful and send a response in a lambda with a 200 and a message from the body. I don't want to return the 200 status inside the function because I need to also check if a fetch request is succesful before sending the 200 status with a body back.

Hopefully someone can help with this

let statusTrue

const req = https.request(options, function(res) {
 res.setEncoding("utf8")
 res.on("data", function(body) {
   console.log(`Body: ${body}`)
   statusTrue = body.status
  })
})

 if (statusTrue) {
    return {
      statusCode: 200,
      headers: {
        "Access-Control-Allow-Origin": "*",
      },
      body: JSON.stringify({ email: true }),
    }
  } else {
    return {
      statusCode: 200,
      headers: {
        "Access-Control-Allow-Origin": "*",
      },
      body: JSON.stringify({ email: false }),
    }
  }

Update Heres my code with oswins answer, the full code for context. Right now the function fires after the handler finishes so I never am able to send a proper response back.

const sgMail = require("@sendgrid/mail")
require("dotenv").config()
const { SENDGRID_API_KEY, SENDGRID_TO_EMAIL } = process.env
const URL = require("url")
const https = require("https")
const fetch = require("node-fetch")

exports.handler = async (event, context) => {
  try {
    //console.log(JSON.parse(event.body))

    //*** send off to google to verify captcha */

    const body = JSON.parse(event.body)

    let secret = "fdsf"
    const fetchUrl = `https://www.google.com/recaptcha/api/siteverify?secret=${secret}&response=${body.captcha}&remoteip=${event.headers["client-ip"]}`
    let isItTrue
    await fetch(fetchUrl, {
      method: "POST",
      body: JSON.stringify({ message: "hello world" }),
      headers: { "Content-Type": "application/json" },
    })
      .then(response => response.json())
      .then(data => {
        isItTrue = data.success
      })
      .catch(error => {
        console.error("Error:", error)
      })

    //console.log(isItTrue)

    //*** end */

    //*** Running Form Sends Now if Captcha Valid */

    if (isItTrue) {
      //*** Zapier Send */

      const webhook_url = URL.parse(
        "https://hooks.zapier.com/hooks/catch/fds"
      )
      const options = {
        hostname: webhook_url.hostname,
        path: webhook_url.pathname,
        method: "POST",
        headers: { "Content-Type": "application/json" },
      }
      // Set up webhook request

      const req = https.request(options, function(res) {
        res.setEncoding("utf8")
        res.on("data", function(body) {
          console.log(`Body: ${body}`)
          sendResponse(body.status)
        })
      })

      // Handle webhook request error
      req.on("error", function(e) {
        const errorMessage = `[ERROR] Problem with request: ${e.message}`
        console.log(errorMessage)
        callback(e.message, {
          statusCode: 400,
          body: errorMessage,
        })
      })
      // Send form data to webhook request and end request
      req.end(JSON.stringify(body.data))

      //*** End */

      //console.log(zapierStatus)

      const sendResponse = statusTrue => {
        if (statusTrue === "success") {
          return {
            statusCode: 200,
            headers: {
              "Access-Control-Allow-Origin": "*",
            },
            body: JSON.stringify({ email: true }),
          }
        } else {
          return {
            statusCode: 200,
            headers: {
              "Access-Control-Allow-Origin": "*",
            },
            body: JSON.stringify({ email: false }),
          }
        }
      }
    } else {
      return {
        statusCode: 200,
        headers: {
          "Access-Control-Allow-Origin": "*",
        },
        body: JSON.stringify({ captcha: false }),
      }
    }

    //*** end */
  } catch (err) {
    return { statusCode: 500, body: err.toString() }
  }
}
Anders Kitson
  • 1,413
  • 6
  • 38
  • 98
  • You don't get the value outside the function except when using the techniques inside [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) . Follow the directions there. – jfriend00 May 25 '20 at 18:24
  • You use the value inside the callback or you call some other function from within the callback and you pass it the value. That's how asynchronous programming works in Javascript. If you want a more friendly way to program this, you will use an http library that supports promises such as [`got()`](https://www.npmjs.com/package/got) and program with promises and `async/await`. – jfriend00 May 25 '20 at 18:25

2 Answers2

1

Maybe wrapping statements outside the function into another function will help ;-)

const req = https.request(options, function (res) {
    res.setEncoding("utf8")
    res.on("data", function (body) {
        console.log(`Body: ${body}`)
        statusTrue = body.status
        sendResponse(statusTrue)
    })
})

function sendResponse(statusTrue) {
    if (statusTrue) {
        return {
            statusCode: 200,
            headers: {
                "Access-Control-Allow-Origin": "*",
            },
            body: JSON.stringify({ email: true }),
        }
    } else {
        return {
            statusCode: 200,
            headers: {
                "Access-Control-Allow-Origin": "*",
            },
            body: JSON.stringify({ email: false }),
        }
    }
}
Oswin
  • 11
  • 1
0

You can wrap your https.request call in a promise like this:

const makeRequest = function(options) {
    return new Promise(function(resolve, reject) {
        const req = https.request(options, function(res) {
        res.setEncoding("utf8")
        res.on("error", reject)
        res.on("data", function(body) {
            console.log(`Body: ${body}`)
            resolve(body.status)
        })
    })
}

Then later you can do:

makeRequest({/*options*/})
.then(function(statusTrue) {
    if (statusTrue) {
        return {
            statusCode: 200,
            headers: {
                "Access-Control-Allow-Origin": "*",
            },
            body: JSON.stringify({ email: true }),
        }
    } else {
        return {
            statusCode: 200,
            headers: {
                "Access-Control-Allow-Origin": "*",
            },
            body: JSON.stringify({ email: false }),
        }
    }
})
.then(function(ret) {
    console.log(ret)
})
.catch(function(err) {
    /* handle error */
})
Marco
  • 7,007
  • 2
  • 19
  • 49
  • I Updated my question with my full code, I have a few more functions that interact with the .req so not sure how ti implement your solution do I place them in side the makeRequest function as well. – Anders Kitson May 25 '20 at 19:49