首页 > 解决方案 > Node.js - AWS - 程序在上传到 S3 存储桶完成之前终止

问题描述

我编写了一个创建 HTML 文件的程序。然后,我尝试在程序结束时将文件上传到我的 S3 存储桶。似乎问题在于我的程序在允许函数完成或从函数接收回调之前终止。

这是我的代码的要点:

let aws = require('aws-sdk');

aws.config.update({
    //Censored keys for security
    accessKeyId: '*****',
    secretAccessKey: '*****',
    region: 'us-west-2'
});

let s3 = new aws.S3({
    apiVersion: "2006-03-01",
});

function upload(folder, platform, browser, title, data){
    s3.upload({
        Bucket: 'html',
        Key: folder + platform + '/' + browser + '/' + title + '.html',
        Body: data
    },  function (err, data) {
        if (err) {
            console.log("Error: ", err);
        }
        if (data) {
            console.log("Success: ", data.Location);
        }
    });
}

/*
*
* Here is where the program generates HTML files
*
*/

upload(folder, platform, browser, title, data);

如果我在upload()代码的 HTML 生成部分之前调用该函数(配置了测试/虚拟数据),则上传成功。测试文件成功上传到 S3。但是,当在我的代码末尾调用该函数时,我没有收到错误或成功响应。相反,程序只是终止并且文件没有上传到 S3。

upload()有没有办法在继续程序之前等待我的函数的回调?在将文件上传到 S3 之前,如何防止程序终止?谢谢!

编辑:实施Deiv的回答后,我发现该程序仍然没有上传我的文件。我仍然没有收到任何类型的成功或错误消息。实际上,程序似乎只是跳过了该upload()功能。为了测试这一点,我console.log("test")在调用后添加了一个upload()以查看它是否会执行。果然,日志打印成功。

以下是有关该项目的更多信息:我正在利用 WebdriverIO v4 创建各种测试通过/失败的 HTML 报告。this.on('test:start')我通过多个事件侦听器(例如、this.on('suite:end')等)收集测试结果。最后一个事件是this.on('end'),当所有测试都完成执行时调用。在这里,测试结果是根据运行的操作系统、浏览器等进行排序的。

我现在注意到我的程序不会在this.on('end')事件处理程序中执行任何与 S3 相关的操作,即使我将它放在处理程序的开头,尽管我仍然相信这是因为它没有足够的时间来执行因为处理程序能够非常快速地处理结果并创建 HTML 文件。我有这段代码列出了我的 S3 中的所有存储桶:

s3.listBuckets(function (err, data) {
    if (err) {
        console.log("Error: ", err);
    } else {
        console.log("Success: ", data.Buckets);
    }
});

即使这在开头运行时也不会返回任何类型的结果this.on('end')。有没有人有任何想法?我真的很难过。

编辑:这是我实现 Naveen 建议的新代码:

this.on('end', async (end) => {

/*
* Program sorts results and creates variable 'data', the contents of the HTML file.
*/

    await s3.upload({
        Bucket: 'html',
        Key: key,
        Body: data
    }, function (err, data) {
        if (err) {
            console.log("Error: ", err);
        }
        if (data) {
            console.log("Success: ", data.Location);
        }
    }).on('httpUploadProgress', event => {
        console.log(`Uploaded ${event.loaded} out of ${event.total}`);
    });
}

逻辑看起来很合理,但我仍然没有收到成功或错误消息,而且我没有看到上传进度。HTML 文件不会上传到 S3。

标签: node.jsamazon-web-servicesasynchronousamazon-s3webdriver-io

解决方案


您可以使用 Promise 等待上传功能完成。这是它的样子:

function upload(folder, platform, browser, title, data) {
    return new Promise((resolve, reject) => {
        s3.upload({
            Bucket: 'html',
            Key: folder + platform + '/' + browser + '/' + title + '.html',
            Body: data
        }, function(err, data) {
            if (err) {
                console.log("Error: ", err);
                return reject(err);
            }
            if (data) {
                console.log("Success: ", data.Location);
                return resolve();   //potentially return resolve(data) if you need the data
            }
        });
    });
}

/*
*
* Here is where the program generates HTML files
*
*/

upload(folder, platform, browser, title, data)
    .then(data => { //if you don't care for the data returned, you can also do .then(() => {
        //handle success, do whatever else you want, such as calling callback to end the function
    })
    .catch(error => {
        //handle error
    }

推荐阅读