我想了解为什么在以下情况下不会调用setImmediate的回调:
module.exports.handler = async (event, context, callback) => {
try {
console.log('calling setImmediate...');
setImmediate(function () {
console.log('setImmediate callback invoked!');
callback(null, 'OK!!!!');
})
} catch (e) {
console.log('Failed!');
console.log(e);
callback(e);
}
};
CloudWatch中的输出如下:
START RequestId: c2b83f7b-e37a-11e8-ba70-5b99f76ce7ed Version: $LATEST
2018-11-08T17:21:42.922Z c2b83f7b-e37a-11e8-ba70-5b99f76ce7ed calling setImmediate...
END RequestId: c2b83f7b-e37a-11e8-ba70-5b99f76ce7ed
REPORT RequestId: c2b83f7b-e37a-11e8-ba70-5b99f76ce7ed Duration: 35.99 ms Billed Duration: 100 ms Memory Size: 128 MB Max Memory Used: 19 MB
删除'async'关键字即可解决,但我不明白为什么。
我尝试在lambda环境之外重现此行为:
async function test(){
setImmediate(function(){
console.log('setImmediate callback!')
})
}
test()
但是在此示例中,回调被调用。
任何人都可以指出正确的方向来理解这一点吗?
答案 0 :(得分:1)
如果您返回async
函数所做的诺言,则当诺言得到解决时,您的lambda会结束。由于您的异步函数不包含任何await
表达式,因此它返回的承诺将立即得到解决。您不能同时进行回调并返回承诺。
对于await
上的setImmediate
,您必须创建一个承诺,该承诺将在其回调触发时解析。将您的callback(e)
转换为被拒绝的承诺,并将您的callback(null, 'OK!!!!')
转换为已解决的承诺:
module.exports.handler = async (event, context) => {
try {
console.log('calling setImmediate...');
return await new Promise((resolve, reject) => {
setImmediate(function () {
console.log('setImmediate callback invoked!');
resolve('OK!!!!');
});
});
} catch (e) {
console.log('Failed!');
console.log(e);
throw e;
}
};
答案 1 :(得分:0)
在节点8中使用异步调用处理程序时,您不应使用回调。
在节点8中声明为异步的函数实际上正在返回诺言。因为您正在声明回调,所以setImmediate函数试图解析第二个Promise,因此您实际上已经设置了一个竞争条件,其中lambda在函数内部运行控制台日志语句之前结束。无论哪种方式,您实际上都不会得到想要的响应。
尝试:
module.exports.handler = async (event, context) => {
try {
console.log('calling setImmediate...');
var setImmediate = (function () {
console.log('setImmediate callback invoked!');
return('OK!!!!');
});
return setImmediate();
} catch (e) {
console.log('Failed!');
console.log(e);
return(e);
}
};
如果删除异步声明,您的代码将起作用,因为仍然支持旧的回调语法。