Azure Table 服务 retrieveEntity "skipping" 函数

Azure Table Service retrieveEntity "skipping" the function

我有一个将信息存储到 Azure 表的聊天机器人。在一个用例中,我需要检查实体是否存在,如果存在,则将电子邮件地址附加到实体中的字段并更新它。我正在使用 azure-storage 包。当我第一次开始测试时它工作正常,但经过几次迭代后它开始跳过该功能。我一直在使用调试器并见证了它通过函数的 if (!err) 部分。但是,在不更改(据我所知)任何代码的情况下,它现在跳过了整个函数。我在 if 和 else 语句以及函数的末尾放置了额外的断点,但它只是绕过所有内容并直接进入下一个代码块。下一个块替换了实体,它实际上工作正常。只有 retrieveEntity 不工作。我不知道为什么这行不通。有任何想法吗?从功能上讲,我看不出它根本无法进入功能块的任何原因,而且我更困惑的是它在某一时刻工作。这是 retrieveEntity 和 insertOrReplaceEntity 的代码块。

            tableSvc.retrieveEntity('orderData', 'Vista', lineKey, function(err, result, response) {
                if (!err) {
                    if (!result.userEmail._.includes(conversationData.userEmail)) {
                        notifyEmail = `${result.userEmail._}, ${conversationData.userEmail}`;
                    } else {
                        notifyEmail = result.userEmail._;
                    }
                } else {
                    notifyEmail = conversationData.userEmail;
                }
            });

<<some code to define lineData for entity>>

                tableSvc.insertOrReplaceEntity('orderData',lineData, async function (err, result, response) {
                    if (!err) {
                        await step.context.sendActivity('OK, I will let you know once this line item ships.');
                        this.appInsightsClient.trackTrace({message: `Table API - ${path.basename(__filename)}`,severity: 1,properties: {request:lineData, response:response} });
                    } else {
                        console.log(err);
                        await step.context.sendActivity(`I wasn't able to set up that notification for you. Please try your search again later, and if your line still hasn't shipped I can try to set it up again.`);
                        this.appInsightsClient.trackTrace({message: `${err.name}/${err.code} - ${path.basename(__filename)}`,severity: 4,properties: {'request':lineData, 'error':err.message} });
                    }
                });

考虑到 tableSvc.retrieveEntity 是一个异步操作(因为它进行网络调用并等待响应到来),最好等待它的结果。我同意你的看法,等待预定时间间隔(在你的情况下为 1.5 秒)不是最佳解决方案。

一种可能的解决方案是将检索实体的调用包装在 returns 一个 Promise 的函数中,以便您等待该承诺得到实现。

这是我想出的伪代码(未测试):

function retrieveEntity() {
    return new Promise((resolve) => {
        tableSvc.retrieveEntity('orderData', 'Vista', lineKey, function(err, result, response) {
            if (!err) {
                if (!result.userEmail._.includes(conversationData.userEmail)) {
                    notifyEmail = `${result.userEmail._}, ${conversationData.userEmail}`;
                } else {
                    notifyEmail = result.userEmail._;
                }
                resolve(notifyEmail);
            } else {
                notifyEmail = conversationData.userEmail;
                resolve(notifyEmail);
            }
        });
    });
}

retrieveEntity
.then((result) => {
    //some code to define lineData for entity
    //
    //

    tableSvc.insertOrReplaceEntity('orderData',lineData, async function (err, result, response) {
        if (!err) {
            await step.context.sendActivity('OK, I will let you know once this line item ships.');
            this.appInsightsClient.trackTrace({message: `Table API - ${path.basename(__filename)}`,severity: 1,properties: {request:lineData, response:response} });
        } else {
            console.log(err);
            await step.context.sendActivity(`I wasn't able to set up that notification for you. Please try your search again later, and if your line still hasn't shipped I can try to set it up again.`);
            this.appInsightsClient.trackTrace({message: `${err.name}/${err.code} - ${path.basename(__filename)}`,severity: 4,properties: {'request':lineData, 'error':err.message} });
        }
    });
});

根据@Gaurav Mantri 发布的内容,我得到了答案。我需要使用 async/await 来处理 botframework 活动,此外,这还允许我只包装 retrieveEntity 函数而不包装其余代码。这是我的解决方法。

            async function retrieveEntity() {
                return new Promise((resolve) => {
                    tableSvc.retrieveEntity('orderData', 'Vista', lineKey, function(err, result, response) {
                        if (!err) {
                            console.log(result.userEmail._, conversationData.userEmail);
                            if (!result.userEmail._.includes(conversationData.userEmail)) {
                                notifyEmail = `${result.userEmail._},${conversationData.userEmail}`;
                            } else {
                                notifyEmail = result.userEmail._;
                            }
                            resolve(notifyEmail);
                        } else {
                            notifyEmail = conversationData.userEmail;
                            resolve(notifyEmail);
                        }
                    });
                }); 
            }
            await retrieveEntity();

关键(对于大多数资深编码员来说可能显而易见)是我必须 return 一个承诺。否则它只是在等待我对 tableSvc 的调用,因此我就回到了开始的地方。以这种方式设置,对 retrieveEntity 的调用等待解析 resolve(notifyEmail),然后在该值可用的情况下,我的函数的其余部分按要求工作。