s3.getObject 或 s3.putObject 可以用在 Promise.then() 块中吗?

Can s3.getObject or s3.putObject be used in Promise.then() block?

我需要测试一个对象是否存在于S3存储桶中,如果存在,我需要下载该对象,如果不存在,则创建该对象。我的代码如下所示:

let params = {
    Bucket: bucket,
    Key: fileName,        
};

const function async () => {
    await s3.headObject(params).promise()
    .then(() => {
        s3.getObject(params)
        .promise()
        .then(response => {
            console.log(response.Body.toISOString());
        });
    })
    .catch((err) => {
        if (err.code == "NotFound") {
            s3.putObject({
                Body: event,
                Bucket: bucket,
                Key: fileName,                  
            });
        }
    });
}

它似乎不起作用,问题可能是在 then 或 catch 块中嵌套 s3.getObject 或 s3.putObject 调用。我试过在 s3.getObject/s3.putObject 之前添加 await,还是不行。

您必须 return 从它们的 .then() 处理程序中嵌套承诺,以便正确链接承诺。但是,如果您要使用 async/await,最好甚至不使用 .then(),而只使用 await 而不要嵌套。通常,您不希望混合使用 await.then(),因为这会使正确的流程和错误处理变得复杂。

这是一个您只使用 await 并且所有承诺都正确排序的版本:

const params = {
    Bucket: bucket,
    Key: fileName,
};

async function someFunction() {
    try {
        await s3.headObject(params).promise();
        let response = await s3.getObject(params).promise();
        console.log(response.Body.toISOString());
        return response.Body;
    } catch (err) {
        if (err.code == "NotFound") {
            await s3.putObject({
                Body: event,
                Bucket: bucket,
                Key: fileName,
            }).promise();
        } else {
            throw err;
        }
    }
}

仅供参考,您似乎 could/should 删除了函数的 headObject() 部分。看来您所做的只是检查对象是否存在,并且 getObject() 应该已经做了同样的事情。因此,只需正确处理 getObject() 上的错误,您就可以像这样删除 headObject()

const params = {
    Bucket: bucket,
    Key: fileName,
};

async function someFunction() {
    try {
        let response = await s3.getObject(params).promise();
        console.log(response.Body.toISOString());
        return response.Body;
    } catch (err) {
        if (err.code == "NotFound") {
            await s3.putObject({
                Body: event,
                Bucket: bucket,
                Key: fileName,
            }).promise();
        } else {
            throw err;
        }
    }
}

注意:如果两段代码同时尝试添加具有相同键的对象,则此代码会出现竞争条件。那是因为在检查对象是否存在的时间和添加它的时间之间存在竞争条件 window,另一个代码线程可以添加该对象,然后您将覆盖该对象或以重复项结束(取决于data-store 已配置)。您检查它是否存在然后添加它的代码不是原子的。

这是经典data-storemistake/error。我不知道 s3 API 的详细信息,但总的来说,您应该配置数据存储,以便只允许一个具有给定键的对象,您只需尝试添加新对象,如果它已经存在存在相同的键,你只是得到一个错误,它已经存在,或者你在 data-store 中使用一个特定的原子函数来添加它,如果它不存在的话。