首页 > 数据库 >【Azure 应用服务】Azure JS Function 异步方法中执行SQL查询后,Callback函数中日志无法输出问题

【Azure 应用服务】Azure JS Function 异步方法中执行SQL查询后,Callback函数中日志无法输出问题

时间:2023-05-06 20:55:23浏览次数:47  
标签:Function function log callDBtoOutput JS context sql Azure name

问题描述

开发 Azure JS Function(NodeJS),使用 mssql 组件操作数据库。当SQL语句执行完成后,在Callback函数中执行日志输出 context.log(" ...") , 遇见如下错误:

Warning: Unexpected call to 'log' on the context object after function execution has completed.

Please check for asynchronous calls that are not awaited or calls to 'done' made before function execution completes. 

Function name: HttpTrigger1. Invocation Id: e8c69eb5-fcbc-451c-8ee6-c130ba86c0e9. Learn more: https://go.microsoft.com/fwlink/?linkid=2097909

错误截图

 

问题解答

JS 函数代码(日志无法正常输出)

var sql = require('mssql');
var config = {
    user: 'username',
    password: 'Password',
    server: '<server name>.database.chinacloudapi.cn', // You can use 'localhost\\instance' to connect to named instance
    database: 'db name',

    options: {
        encrypt: true // Use this if you're on Windows Azure
    }
}
module.exports = async function (context, req) { context.log('JavaScript HTTP trigger function processed a request.'); await callDBtoOutput(context); context.log('################'); //Default Code ... const name = (req.query.name || (req.body && req.body.name)); const responseMessage = name ? "Hello, " + name + ". This HTTP triggered function executed successfully." : "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."; context.res = { // status: 200, /* Defaults to 200 */ body: responseMessage }; } async function callDBtoOutput(context) { try { context.log("Some Message from callDBtoOutput") var ps = new sql.PreparedStatement(await sql.connect(config)) await ps.prepare('SELECT SUSER_SNAME() ', async function (err) { if (err) { context.log(err) } context.log("start to exec sql ...from callDBtoOutput") await ps.execute({}, async function (err, recordset) { // ... error checks context.log(recordset) context.log("Login SQL DB successfully....from callDBtoOutput") ps.unprepare(function (err) { // ... error checks }); }); }); } catch (error) { context.log(`Some Error Log: from callDBtoOutput`, error); } }

在 callDBtoOutput() 函数中,调用sql prepare 和 execute方法执行sql语句,虽然已经使用了async和await关键字,但根据测试结果表明:Function的主线程并不会等待callback函数执行。当主线程中context对象释放后,子线程中继续执行context.log函数时就会遇见以上警告信息。 

 

为了解决以上prepare和execute方法中日志输出问题,需要使用其他执行sql的方法。在查看mssql的官方说明(https://www.npmjs.com/package/mssql#query-command-callback)后,发现query方法能够满足要求。

query (command, [callback])

Execute the SQL command. To execute commands like create procedure or if you plan to work with local temporary tables, use batch instead.

Arguments

  • command - T-SQL command to be executed.
  • callback(err, recordset) - A callback which is called after execution has completed, or an error has occurred. Optional. If omitted, returns Promise.

 

经过多次测试,以下代码能完整输出Function过程中产生的日志。

JS 函数执行SQL代码(日志正常输出)

var sql = require('mssql');

var config = {
    user: 'username',
    password: 'Password',
    server: '<server name>.database.chinacloudapi.cn', // You can use 'localhost\\instance' to connect to named instance
    database: 'db name',

    options: {
        encrypt: true // Use this if you're on Windows Azure
    }
}

module.exports = async function (context, req) {
    context.log('JavaScript HTTP trigger function processed a request.');
    
    // context.log('call callDBtoOutput 1');
    // await callDBtoOutput(context);

    //context.log('call callDBtoOutput 2');
    await callDBtoOutput2(context);

    context.log('################');
    const name = (req.query.name || (req.body && req.body.name));
    const responseMessage = name
        ? "Hello, " + name + ". This HTTP triggered function executed successfully."
        : "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.";

    context.res = {
        // status: 200, /* Defaults to 200 */
        body: responseMessage
    };
}

async function callDBtoOutput2(context) {
    context.log("1: Call SQL Exec function ....")
    await sql.connect(config).then(async function () {
        // Query
        context.log("2: start to exec sql ... ")     
        await new sql.Request().query('SELECT SUSER_SNAME() ').then(async function (recordset) {
            context.log("3: Login SQL DB successfully.... show the Query result") 
            context.log(recordset);

        }).catch(function (err) {
            // ... error checks
        });
    })
    context.log("4: exec sql completed ... ") 
}

结果展示(完整日志输出)

 

参考资料

node-mssql: https://www.npmjs.com/package/mssql

context.done : https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-node?pivots=nodejs-model-v3&tabs=javascript%2Cwindows-setting-the-node-version#contextdone

The context.done method is deprecated

Now, it's recommended to remove the call to context.done() and mark your function as async so that it returns a promise (even if you don't await anything).

标签:Function,function,log,callDBtoOutput,JS,context,sql,Azure,name
From: https://www.cnblogs.com/lulight/p/17378446.html

相关文章

  • js 打印页面局部区域(指定位置)
    1.情景展示在浏览器的网页上,我们可以通过window.print()实现网页的打印功能。但是,该方法打印的是当前网页上面所有展示的内容,如何只打印指定区域内容呢?如下图所示,只将送检申请单所在区域打印出来,其它位置不用管,如何实现?2.具体分析window.print()打印的是全部内容,那我们就......
  • 记一次使用laravel-snappy把g2和plotly.js图生成pdf踩坑经历
    最近有一个需求,需要把页面上的echarts等js组件生成的图表放到pdf中。使用laravel框架,找到了laravel-snappy这个包,其底层是使用wkhtmltopdf来生成pdf。因为有把数据点都画到箱型图上的需求,找到了plotly.js这个组件,功能还是很强大的,可以轻松实现如下的效果 页面都没问题,然使用lar......
  • 在 iframe 中继承父窗口 css/js 的方法
    问题缘由iframe属于一个单独的文档(单独的网页窗口)不能直接使用父页面的资源,如css和js。如果iframe和父页面同域则可以在iframe中使用parent对象来使用父页的js对象继承css因为iframe是单独的网页窗口,所以页面一般都有head标签的。在iframe子页面的head......
  • 【转载】JS手从URL中获取指定参数,不需要正则,很方便
    参考https://zhuanlan.zhihu.com/p/412254881代码现代方式在现代浏览器中,我们可以使用浏览器提供的URL对象来获取参数。这里方法最简单,bug少,不用我们操心。functiongetQueryString(name){//consturl=newURL(window.location.href);consturl_string="htt......
  • Uncaught TypeError: f.__fbeventsModules[a] is not a function at f.__fbeventsM
    UncaughtTypeError:f.__fbeventsModules[a]isnotafunctionatf.__fbeventsModules.f.getFbeventsModules怎么了这个错误通常是因为代码中使用了Facebook的跟踪代码,但是在加载该代码之前,代码中尝试访问跟踪模块。这个错误有几种可能的原因:Facebook跟踪代码没有正......
  • 常见的js加密方式
      RSA、16进制、Base64都属于可逆加密方式,可以通过相应的解密方法将密文还原为明文。  而哈希算法是不可逆加密方式,只能将明文进行哈希后得到一段固定长度的密文,但无法通过密文还原出明文。其中,SHA算法、MD5算法都是常用的哈希算法。一、16进制加密  加密和解密示例:de......
  • servlet 访问jstl文件出现500情况
    可能原因是导入依赖包出现的问题。<dependency><groupId>javax.servlet.jsp</groupId><artifactId>jsp-api</artifactId><version>2.2</version><scope>provided</scope&g......
  • Three.js教程:访问几何体对象的数据
    推荐:将NSDT场景编辑器加入你的3D工具链其他系列工具:NSDT简石数字孪生访问几何体对象的数据实际开发项目的时候,可能会加载外部模型,有些时候需要获取模型几何体的顶点数据,如果想获取几何体的顶点数据首先要熟悉three.js几何体BoxGeometry和BufferGeometry的结构。访问几何体顶点......
  • Module build failed (from ./node_modules/css-loader/dist/cjs.js): TypeError: thi
    Modulebuildfailed(from./node_modules/css-loader/dist/cjs.js):TypeError:this.getOptionsisnotafunctionModulebuildfailed(from./node_modules/css-loader/dist/cjs.js):TypeError:this.getOptionsisnotafunction 用了各种办法,没有解决问题,直接把node_m......
  • 快速上手UmiJs
    先找个地方建个空目录mkdirmyapp&&cdmyapp通过官方工具创建项目yarncreate@umijs/umi-app#或npx@umijs/umi-appCopy:.editorconfigWrite:.gitignoreCopy:.prettierignoreCopy:.prettierrcWrite:.umirc.tsCopy:mock/.gitkeepWrite:package.json......