这是工作流程:
获取 https 链接 --> 写入文件系统 --> 从文件系统读取 --> 获取 sha256 哈希。
它在运行节点 10.15.3 的本地计算机上运行良好 但是当我在 AWS 上启动 lambda 函数时,输出为空。可读流可能存在一些问题。这是代码。您可以直接在本地计算机上运行它。它将根据需要输出 sha256 哈希。如果您希望在 AWS Lambda 上运行,请按标记进行注释/取消注释。
//Reference: https://stackoverflow.com/questions/11944932/how-to-download-a-file-with-node-js-without-using-third-party-libraries
var https = require('https');
var fs = require('fs');
var crypto = require('crypto')
const url = "https://upload.wikimedia.org/wikipedia/commons/a/a8/TEIDE.JPG"
const dest = "/tmp/doc";
let hexData;
async function writeit(){
var file = fs.createWriteStream(dest);
return new Promise((resolve, reject) => {
var responseSent = false;
https.get(url, response => {
response.pipe(file);
file.on('finish', () =>{
file.close(() => {
if(responseSent) return;
responseSent = true;
resolve();
});
});
}).on('error', err => {
if(responseSent) return;
responseSent = true;
reject(err);
});
});
}
const readit = async () => {
await writeit();
var readandhex = fs.createReadStream(dest).pipe(crypto.createHash('sha256').setEncoding('hex'))
try {
readandhex.on('finish', function () { //MAY BE PROBLEM IS HERE.
console.log(this.read())
fs.unlink(dest, () => {});
})
}
catch (err) {
console.log(err);
return err;
}
}
const handler = async() =>{ //Comment this line to run the code on AWS Lambda
//exports.handler = async (event) => { //UNComment this line to run the code on AWS Lambda
try {
hexData = readit();
}
catch (err) {
console.log(err);
return err;
}
return hexData;
};
handler() //Comment this line to run the code on AWS Lambda
您可能需要检查多个事项。
-
由于您正在访问的 URL 是公有 URL,因此请确保您的 lambda 位于 VPC 外部,或者您的 VPC 具有附加了具有互联网访问权限的 NAT 网关。
-
/tmp
是 lambda 的有效临时目录,但在使用它之前,您可能需要在/tmp
中创建doc
文件夹。
可以检查云监视日志,了解有关启用后发生的情况的详细信息。
我以前见过本地和lambda之间的这种行为差异。
所有异步函数都返回承诺。必须等待异步函数。调用异步函数而不等待它意味着执行继续到下一行,并且可能超出调用函数。
所以你的代码:
exports.handler = async (event) => {
try {
hexData = readit();
}
catch (err) {
console.log(err);
return err;
}
return hexData;
};
readit()
定义为const readit = async () => { ... }
。但是您的处理程序不会等待它。因此,hexData = readit();
将未解析的承诺分配给hexData
,返回它,处理程序退出,Lambda"完成",而没有执行readit()
代码。
然后,简单的解决方法是等待异步功能:hexData = await readit();
。它在节点中本地工作的原因是,即使处理程序函数已经返回,节点进程也会在退出之前等待承诺解析。但是,由于 Lambda 会在处理程序返回后立即"返回",因此未解决的承诺仍未解决。(顺便说一句,writeit
函数不需要标记为异步,因为它不等待任何内容,并且已经返回了一个承诺。
话虽如此,我不太了解承诺,我对事件几乎一无所知。所以还有其他事情为我发出警告标志,但我不确定它们,也许它们很好,但我会在这里提出以防万一:
file.on('finish'
和readandhex.on('finish'
.这两个事件,我相信是非阻塞的,那么为什么处理程序和 lambda 会等待它们呢?
在第一种情况下,它是在一个承诺内,resolve()
是从事件函数中调用的,所以这可能很好(正如我所说,我对这两个主题了解不多,所以不确定) - 重要的是代码必须在这一点上阻塞,直到承诺得到解决。如果代码可以继续执行(即从writeit()
返回),直到引发finish
事件,那么它将不起作用。
第二种情况几乎肯定会是一个问题,因为它只是说如果x 事件被引发,那么做 y。没有等待的承诺,所以没有什么可以阻止代码,所以它会很高兴地继续到readit()
函数的末尾,然后是处理程序和 lambda。同样,这是基于事件是非阻塞的假设(从某种意义上说,你想要对某个事件执行某些代码的声明不会等待该事件的引发)。