处理 aws-sdk 存储桶创建请求 nodejs express

Handling aws-sdk bucket creation requests nodejs express

我有以下代码。主要目的是通过 aws-sdk 创建一个桶,如果成功,为相关条目生成一个数据库记录。但是有几个问题

const AWS  = require('aws-sdk');
const router = require('express').Router();

const Bucket = require("../../../models/bucket_bucket");

const { v4: uuidv4 } = require('uuid');

require('dotenv').config();

AWS.config.logger = console;

s3 = new AWS.S3({
    // apiVersion: '2006-03-01',
    accessKeyId: process.env.AWS_ACCESS_KEY_ID,
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
    region: process.env.AWS_REGION
});

// Accepts Bucket Name, Bucket Created User/ Belonging Organization
router.post('/create', (req, res, next)=>{

    var requestBucketParams = {
        Bucket: req.body.bucket
    }

    var isBucketCreationSuccess = false;

    var createRequestBucketPromise = s3.createBucket(requestBucketParams).promise();
    var createDeliveryBucketPromise = s3.createBucket(deliveryBucketParams).promise();

    createRequestBucketPromise.then((data)=>{
        isBucketCreationSuccess = true;
    }).catch((err)=>{
        res.send({
            message: "error while creating the bucket",
            description: err.message
        });
    });
    
    console.log(isBucketCreationSuccess);

        
    if(isBucketCreationSuccess){
        Bucket.create({
            bucketId: uuidv4(),
            name: req.body.bucket,
            bucket_url: "http://" + req.body.bucket + ".s3.amazonaws.com",
        }).then(bucket=>{
            res.send({
                url: "http://" + req.body.bucket + ".s3.amazonaws.com",
            })
        }).catch(err=>{
            res.send({
                message: err.message
            })
        })
    }else{
        res.send({
            message: "Database record creation failed"
        })
    }

});

所以我有2个问题(请耐心等待,我对nodejs不是很熟悉)

  1. isBucketCreationSuccess 总是 false 无论我如何尝试设置它。我相信这与异步有关。但是不行
  2. 这会产生以下错误
(node:25293) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
   at ServerResponse.setHeader (_http_outgoing.js:543:11)
   at ServerResponse.header (/home/caesar/Workspace/res-s3/res-s3-backend/node_modules/express/lib/response.js:771:10)
   at ServerResponse.send (/home/caesar/Workspace/res-s3/res-s3-backend/node_modules/express/lib/response.js:170:12)
   at ServerResponse.json (/home/caesar/Workspace/res-s3/res-s3-backend/node_modules/express/lib/response.js:267:15)
   at ServerResponse.send (/home/caesar/Workspace/res-s3/res-s3-backend/node_modules/express/lib/response.js:158:21)
   at /home/caesar/Workspace/res-s3/res-s3-backend/routes/api/bucket/index.js:54:13
   at processTicksAndRejections (internal/process/task_queues.js:93:5)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:25293) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:25293) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
[AWS s3 409 2.197s 0 retries] createBucket({
 Bucket: 'delivery-bucket-1',
 CreateBucketConfiguration: { LocationConstraint: 'eu-west-1' }
})

您遇到的问题与Nodejs无关。我建议刷新你对 Promise and Async/Await

的了解

您分享的代码似乎不完整。我会尝试用你分享的内容来解释这个想法。

then/catch 之外的代码语句同步执行。

createRequestBucketPromise.then((data)=>{
  isBucketCreationSuccess = true;
})
.catch((err)=>{
  res.send({
    message: "error while creating the bucket",
    description: err.message
  });
});

// This will get executed before above promise handler
console.log(isBucketCreationSuccess);

下面显示的承诺没有导致警告的错误处理程序

var createDeliveryBucketPromise = s3.createBucket(deliveryBucketParams).promise();

你可以这样做来解决问题,但我推荐第二个选项,即使用 Async

使用 Promise

router.post('/create', (req, res, next)=>{
    // const or let is prefered over var
    const requestBucketParams = {
        Bucket: req.body.bucket
    },
    bucketUrl = `https://${req.body.bucket}.s3.amazonaws.com`;

    return s3.createBucket(requestBucketParams).promise()
    .then((data) => {
        return Bucket.create({
            bucketId: uuidv4(),
            name: req.body.bucket,
            bucket_url: bucketUrl,
        });
    })
    .then((bucket) => {
        return res.send({
            url: bucketUrl,
        });
    })
    .catch((err)=>{
        // try to differentiate between aws error and you database error
        // and respond. There are multiple ways to achieve that
    });
});

使用Async/Await

router.post('/create', async (req, res, next) => {
    // const or let is prefered over var
    const requestBucketParams = {
        Bucket: req.body.bucket
    },
    bucketUrl = `https://${req.body.bucket}.s3.amazonaws.com`;

    try {
        await s3.createBucket(requestBucketParams).promise();
    } catch (err) {
        return res.send({
            message: "error while creating the bucket",
            description: err.message
        });
    }
    
    try{
        await Bucket.create({
            bucketId: uuidv4(),
            name: req.body.bucket,
            bucket_url: bucketUrl,
        });
    } catch (err) {
        return res.send({
            message: "Database record creation failed"
        });
    }

    return res.send({
        url: bucketUrl,
    });
});