node.js异步azure队列存储输出绑定

时间:2018-02-05 14:29:51

标签: javascript azure-functions

我正在尝试创建一个JS函数,该函数从存储中读取文件,将其内容写入数据库并将结果消息推送到队列。读取和数据库处理都没问题,但写入队列时没有任何反应。

代码如下:

    process(file)
   .then(() => {
      context.bindings.outQueue = { file };
      return context.log('File processing completed successfully');
    })
    .catch(err => context.log.error(err));

如果我使用context.done()代替,我会收到以下错误:

Error: Choose either to return a promise or call 'done'.  Do not use both in your script.

在任何一种情况下都没有消息写入队列。 怎么了?

1 个答案:

答案 0 :(得分:1)

有几件事最有可能导致你的问题。 首先,您应该在函数的主要范围内返回。不返回将导致您的Function App挂起,这可能是您尝试添加context.done()的原因。 其次,当它可能过早返回时,不应调用context.done()。您看到的错误消息是试图阻止您这样做。 第三,你应该返回你的链式承诺,而不是调用context.done()`。这是让你正确写入队列的原因。

至于第一点:我认为你假设在.then(() => { ... });内返回正在为更大范围的函数返回。请记住,传递给.then()方法的lambda函数只返回一个履行值,该值用于将一个承诺的结果传递给另一个承诺(docs here)。作为附注,我建议不要回复context.log('File processing completed successfully');(只是打电话给它,不要回复它),因为这与返回void相同,但会导致代码更加混乱。

到第二点:在.then(() => { ... });内调用context.done()调用一个方法来指示fork&#d;异步函数中的 main 函数。这很危险,因为从理论上讲,在定义.then(() => { ... });之后的任何时候,主函数代码都可能被对context.done()的调用所杀死。

到第三点:如果你只是在main函数的范围内调用context.done()而不是返回promise,那么你将遇到与#2相反的问题(主代码将退出并停止执行异步代码完成之前的fork异步任务)。

这是一个简单的JS函数的例子,它等待一个promise并写入一个队列:

示例:

module.exports = function (context, req) {
     context.log("Starting function");

    // Mock Promise
    let doWork = new Promise(
       (resolve, reject) => {
            setTimeout(resolve, 100, 'foo');
            console.log("Work in promise");
        }
    );

    doWork.then(() => {
        context.log("Work AFTER promise");
        context.bindings.queue1= "Queue message";
        context.log("Message queued!");
    }).catch(err => context.log.error(err));

    // This is the correct scope to return promise
    return doWork;
};