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

azure,应用服务,js,function,异步,方法,执行,sql,查询,callback,函数,日志,无法,输出,问题 · 浏览次数 : 85

小编点评

**问题描述:** 在使用mssql组件在Azure JS Function(NodeJS)中操作数据库时,遇到日志输出问题。当执行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. ``` **解决方案:** 为了解决此问题,需要使用其他执行 SQL 方法来替代 `context.log`。根据测试结果,`query` 方法能够满足要求,因为它能够执行 SQL 语句并返回结果。 **代码示例:** ```javascript const sql = require('mssql'); var config = { user: 'username', password: 'Password', server: '<server name>.database.chinacloudapi.cn', database: 'db name', options: { encrypt: true } }; module.exports = async function (context, req) { context.log('JavaScript HTTP trigger function processed a request.'); // Execute SQL statement using query method await sql.query(config, 'SELECT SUSER_SNAME() ').then(recordset => { context.log('Login SQL DB successfully.... show the Query result'); context.log(recordset); }).catch(function (err) { context.log(`Some Error Log: ${err}`); }); // Default code ... context.res = { // status: 200, /* Defaults to 200 */ body: 'Hello, ' + name + '. This HTTP triggered function executed successfully.' }; }; ``` **注意:** * `query` 方法需要在使用之前安装 `mssql` 模块。 * `context.done` 方法已弃用,建议使用 `async` 和 `return` 或 `Promise` 来处理异步操作。

正文

问题描述

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

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

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

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 executi

【Azure 应用服务】Azure Web App 服务默认支持一些 Weak TLS Ciphers Suite,是否有办法自定义修改呢?

问题描述 当 Azure Web App 进行安全扫描后,发现依旧支持很多弱TLS加密套件(Weak TLS Ciphers Suite),那么是否有办法来关闭这些弱的加密套件呢? 在Windows IIS环境中,可以通过修改注册表修改 For Microsoft IIS, you should m

【Azure 应用服务】Azure Powershell Function 出错 The term 'Connect-AzAccount' is not recognized

问题描述 在Azure Function中,执行Powershell的Function脚本时,先后出现 1:[Error] ERROR: The term 'Connect-AzAccount' is not recognized as a name of a cmdlet, function, s

【Azure 应用服务】Azure Function Timer触发函数加上Singleton后的问题

问题描述 在Azure Function Timer Trigger的函数中,添加了Singleton属性,当Function的实例变为3个后,发现Timer函数并没有在三个实例上同时运行,每次触发时,都只有在一个实例上运行。这时因为Singleton属性的原因吗? 问题解答 在调查Singleto

【Azure 应用服务】Azure Function Python函数部署到Azure后遇见 Value cannot be null. (Parameter 'receiverConnectionString') 错误

问题描述 使用VS Code创建Python Function,处理Event Hub中的数据。当部署到Azure Function App后,函数无法执行,查看 Function 日志出现 Value cannot be null. (Parameter 'receiverConnectionSt

【Azure 应用服务】Azure Function Python函数中,如何获取Event Hub Trigger的消息Event所属于的PartitionID呢?

问题描述 在通过Azure Function消费Event Hub中的消息时,我们从Function 的 Trigger Details 日志中,可以获得当前Funciton中处理的消息是哪一个分区(PartitionID), 偏移量Offset,序列号SequenceNumber 等信息。 但是在

【Azure 应用服务】Azure Function 部署槽交换时,一不小心把预生产槽上的配置参数交换到生产槽上,引发生产错误

问题描述 部署Function代码先到预生产槽中,进行测试后通过交换方式,把预生产槽中的代码交换到生产槽上,因为在预生产槽中的设置参数值与生产槽有不同,但是在交换的时候,没有仔细检查。导致在交换的时候,把预生产的一些设置值交换到生产中,引起生产错误。 那么是否只进行代码交换而不进行设置值的交换呢?

【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数

问题描述 在Azure App Service for Windows的环境中,部署.NET应用,其中使用了 SAP NetWeaver RFC函数 (需要加载 sapnwrfc.dll)。详细的错误为: “System.DllNotFoundException: Unable to load DL

【Azure 应用服务】Azure Data Factory中调用Function App遇见403 - Forbidden

问题描述 在Azure Data Factory (数据工厂)中,调用同在Azure中的Function App函数,却出现403 - Forbidden错误。 截图如下: 问题解答 访问Azure Function App遇见403 - Forbidden错误,这是因为Function App启用

【Azure 应用服务】Azure Function App在部署时候遇见 503 ServiceUnavailable

问题描述 在VS Code中编写好 Azure Function App代码后,通过 func azure functionapp publish 部署失败,抛出 503 Service Unavailable 错误。 Getting site publishing info... Creating