【问题标题】:Cannot perform http request with http module nodejs azure function无法使用 http 模块 nodejs azure 函数执行 http 请求
【发布时间】:2019-06-04 21:33:35
【问题描述】:

我正在尝试使用节点模块 http 在带有 javascript 的 azure 函数上发出 http 请求,并且由于某种原因 http.request 没有接收数据(没有打印错误,就像请求被阻止一样)。天蓝色配置或代码有什么问题吗?我是否遗漏了一些非常明显的东西?

代码在本地 js 文件上运行良好

context.log('JavaScript timer trigger function ran!', timeStamp); 按预期打印,但 context.log("SUCCESS", JSON.parse(data)); 根本没有打印。

还尝试了不同的库(request、axios)但没有成功


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

    }

【问题讨论】:

  • 你不应该混合异步和回调,你的函数执行很可能在你的回调被调用之前返回。如果您将代码更改为可等待,我认为您应该开始看到您期望的结果。
  • @nelak 我删除了异步但仍然无法正常工作还尝试在 http 上等待但没有成功,也许你有一个我可以使用的最小工作示例?
  • 你能检查http 模块是你依赖的一部分吗? stackoverflow.com/questions/36461247/…
  • 是的http模块加载正确
  • 您使用的是函数运行时版本 1 还是 2 (docs.microsoft.com/en-us/azure/azure-functions/…)?

标签: javascript node.js azure http azure-functions


【解决方案1】:

我使用Axios 重写了您的代码。它支持开箱即用的 async/await,并简化了许多代码以按照您的预期运行,因为它使异步代码像同步代码一样执行。

我认为您可能遇到的主要问题是 JavaScript 中的所有内容都是异步的。因此,Azure 函数运行时在异步函数完成之前退出,因为它没有像发出 HTTP 请求时的同步代码那样阻塞。如果要使用回调,则需要在回调函数中调用 context.done(),以便 Azure 函数在回调完成之前不会退出。通过使用 async/await,您可以保证您的代码将阻塞 HTTP 请求,直到它收到响应或超时。在下面的示例中,Axios 将返回一个包含数据作为元素的响应对象。我正在使用解构操作提取数据,这允许我记录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();
}

在 Azure 函数上安装包

  1. 转到 Azure 门户;选择你的 Azure 函数应用
  2. 选择Platform Features。然后在开发工具Advanced Tools (Kudu)
  3. 使用文件资源管理器导航到site/wwwroot/。您应该会在其中看到一个 package.json 文件,以及几个文件夹,每个文件夹都有您的函数名称。
  4. 从那个目录,运行npm install --save axios
  5. 要确认它有效,请使用铅笔图标编辑您的package.jsonaxios 应列在 dependencies json 元素下

【讨论】:

  • 也对此进行了测试,但不起作用检查上述答案的评论
  • 你运行npm install --save axios了吗?你有堆栈跟踪吗?
  • 没有堆栈跟踪,但 contex.log(axios) 按应有的方式打印库
  • 检查我的答案,这真的很奇怪
  • 如果您复制并粘贴到新的 Azure 计时器函数中,上述代码将按原样运行。我确实必须去诊断控制台安装 Axios。
【解决方案2】:

我一直基于您的代码回调。 我从定义中删除了 async 名字对象,并在 resp.end 处理程序中添加了对 context.done 的调用(这会在函数结束时向函数主机发出信号)

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

}

另一种选择是将函数保留为async,但您需要将回调替换为基于promise 的调用。在某些情况下,这可以通过使用util.promisify 包装它们然后使用await 关键字调用它们来实现

【讨论】:

  • 是的,无法正常工作(在我的 azure acc 上测试过)您是否在您的帐户上进行过测试并且可以正常工作?在同一个问题上运行,re.on end 上没有打印任何内容
  • 抱歉没有工作
  • 我已将此解决方案加载到我的 azure 帐户中的一个函数中,它正在打印预期的结果。
猜你喜欢
  • 1970-01-01
  • 2019-04-14
  • 1970-01-01
  • 2018-03-22
  • 2016-04-08
  • 1970-01-01
  • 2022-08-02
  • 2019-05-12
  • 1970-01-01
相关资源
最近更新 更多