简体   繁体   中英

Cannot perform http request with http module nodejs azure function

I am trying to make a http request with node module http on an azure function with javascript and for some reason http.request is not receiving data(no error printed its like the requested is blocked). There is anything wrong with azure configuration or the code?Am i missing something really obvious?

Code is running fine on local js file

context.log('JavaScript timer trigger function ran!', timeStamp); printed as expected but context.log("SUCCESS", JSON.parse(data)); not printed at all.

Also tryed different libraries (request, axios) with no success


    module.exports = async function (context, myTimer) {
        var timeStamp = new Date().toISOString();

        if (myTimer.IsPastDue)
        {
            context.log('JavaScript is running late!');
        }
        context.log('JavaScript timer trigger function ran!', timeStamp);  

        const http = require('http');
        http.get('http://myAPIurl', (resp) => {
        let data = '';

        // A chunk of data has been recieved.
        resp.on('data', (chunk) => {
          data += chunk;
        });

        // The whole response has been received. Print out the result.
        resp.on('end', () => {
          context.log("SUCCESS", JSON.parse(data));
        });

      }).on("error", (err) => {
      context.log("ERROR: " + err.message);
      });

    }

I rewrote your code using Axios . It has support for async/await out of the box, and simplifies a lot of the code to function as your would expect since it makes asynchronous code perform like synchronous code.

I think the main issue you may have been running into it that everything in JavaScript is async. As a result, the Azure Function runtime was exiting before your async function finished since it didn't block like synchronous code would when making the HTTP request. If you want to use callbacks, you need to call context.done() inside your callback function so the Azure Function doesn't exit before the callback is completed. By using async/await, you can guarantee that your code will block on the HTTP request until it receives a response or timeout. In the example below, Axios will return a response object that includes data as an element. I'm extracting data with a deconstruction operation, which allows me to log data .

const axios = require('axios');
const url = 'https://google.com';

module.exports = async function (context, myTimer) {

  try {
    const { data } = await axios.get(url);
    context.log(data);
    // do something with the data
    return data;
  } catch (err) {
    context.log(err);
    // do something with the error
  }

  context.done();
}

To Install a Package on an Azure Function

  1. Go to the Azure Portal; select your Azure Function App
  2. Select Platform Features . Then Advanced Tools (Kudu) under Development Tools
  3. Using the file explorer, navigate to site/wwwroot/ . You should see a package.json file in there, and several folders each with the name of your functions.
  4. From that directory, run npm install --save axios
  5. To confirm it worked, edit your package.json with the pencil icon. axios should be listed under dependencies json element

I've kept your code callback based. I removed the async moniker from the definition and added a call to context.done (this signals the functions host when your function has ended) in your resp.end handler

module.exports = function (context, myTimer) {
    var timeStamp = new Date().toISOString();

    if (myTimer.IsPastDue)
    {
        context.log('JavaScript is running late!');
    }
    context.log('JavaScript timer trigger function ran!', timeStamp);  

    const https = require('https');
    https.get('https://raw.githubusercontent.com/LearnWebCode/json example/master/animals-1.json', (resp) => {
    let data = '';

    // A chunk of data has been recieved.
    resp.on('data', (chunk) => {
      data += chunk;
    });

    // The whole response has been received. Print out the result.
    resp.on('end', () => {
      context.log("SUCCESS", JSON.parse(data));
      context.done(null, data);
    });

  }).on("error", (err) => {
    context.log("ERROR: " + err.message);
  });

}

Another option would be to keep the function as async but you'd need to replace the callbacks with promise based calls. In some scenarios this can be achieved by wrapping them using util.promisify and then calling them with the await keyword

Ok this will sound weird but i created a new function located on West EU server(insted of US server) and it worked, requests url are toward a EU server.

So this is a network issue of azure? i dont know really

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM