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

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

时间:2023-05-13 22:32:08浏览次数:47  
标签:Function function log JS context sql Azure async name

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. 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).

问题描述

开发 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

错误截图

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

 

问题解答

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 ... ") 
}

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

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

 

参考资料

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,JS,context,sql,Azure,async,name
From: https://blog.51cto.com/u_13773780/6273949

相关文章

  • 【Azure 存储服务】使用 AppendBlobClient 对象实现对Blob进行追加内容操作
    问题描述在AzureBlob的官方示例中,都是对文件进行上传到Blob操作,没有实现对已创建的Blob进行追加的操作。如果想要实现对一个文件的多次追加操作,每一次写入的时候,只传入新的内容? 问题解答AzureStorageBlob有三种类型:BlockBlob,AppendBlob和PageBlob。其中,只有AppendBlo......
  • 爬虫案例之网易有道翻译JS代码复杂版
    网易有道翻译逆向案例本次案例逆向的是网易有道云翻译https://fanyi.youdao.com/index.html#/用到的知识包括requests模块及方法md5加密js代码环境的补全【一】分析网站(1)网站页面如图(2)抓包(3)分析抓到的包逐个查看每个包的标头和载荷在webtranslate这个......
  • js计算一个矩形内部,有一个等比缩放的矩形,如何判断宽和高那个先溢出外层的矩形
    最近在做jscanvas绘图需求时,遇到一个矩形图形重叠逻辑判断问题。一个任意矩形内部,有一个任意等比缩放的矩形,如何判断宽和高那个先溢出外层的矩形?宽和高那个先贴到边上?可以根据两个矩形的比例关系来判断宽和高那个先溢出。首先计算出两个矩形的宽高比,然后比较它们的大小关系。......
  • js计算一个矩形内部,有一个等比缩放的矩形,如何判断宽和高那个先溢出外层的矩形
    最近在做jscanvas绘图需求时,遇到一个矩形图形重叠逻辑判断问题。一个任意矩形内部,有一个任意等比缩放的矩形,如何判断宽和高那个先溢出外层的矩形?宽和高那个先贴到边上?可以根据两个矩形的比例关系来判断宽和高那个先溢出。首先计算出两个矩形的宽高比,然后比较它们的大小关系。......
  • 常用模块,time,random,json,os
    模块底层都是c语言写的模块的分类内置模块,不需要自己安装,直接拿过来用扩展模块,第三方模块,需要自己安装本地编辑器安装小白教程(forchange.cn)random随机数.random()不入参,求(0,1)之间的随机数,开区间.randint(a,b)求随机整数,闭区间[a,b].randrange(start,stop,step......
  • mockjs
    开始mock一个用于拦截ajax请求,并返回模拟数据的库。主要让前端独立于后端进行开发,通过pnpmaddmockjs来进行安装基础初窥门径vardata=Mock.mock({//属性list的值是一个数组,其中含有1到10个元素'list|1-10':[{//属性id是一个自增数,起始值为1......
  • JSP_5.11_课堂笔记
    insert.jsp<%@pageimport="java.sql.Statement"%><%@pageimport="java.sql.Connection"%><%@pageimport="java.sql.DriverManager"%><%@pagelanguage="java"contentType="text/html;charset=UT......
  • Azure创建虚拟机过程解决报错
    Azure创建虚拟机过程解决报错背景​ 当我使用Azure学生教育福利开通虚拟机时(具体步骤建议参考:Azure(az100)和az200建免费虚拟机避抗教程-尘遇(chenyu.me)),在最后的下载个人私钥环节,遇到了以下报错:无法下载SSH私钥。未注册订阅,无法使用命名空间“Microsoft.Compute"。有关如何注......
  • 解决vue.js出现Vue.js not detected错误
    VUEvue-devtools安装成功,但是图标为灰色,且控制台无vue选项的解决办法今天在学习VUE的过程中,安装了vue-devtools工具,但是发现图标一直是灰色,解决后,记录一下解决办法:1.查看拓展程序打开开发者模式和插件,如图所示两个开关,具体操作为:点击浏览器右上角三个点→更多工具→扩展工具......
  • js的一些常用命令
    一、数组相关1.查询数组内单个坐标array.indexof会返回指定元素坐标leta=[1,2,"aa"];letindex_aa=a.indexof("aa")console.log(index_aa)2.删除数组指定坐标array.splice(数组下标,1)会修改原数组的长度deletearr[数组下......