【问题标题】:Getting Multiple Object in AWS S3 with JS Promise All - Nodejs and Express使用 JS Promise All 在 AWS S3 中获取多个对象 - Nodejs 和 Express
【发布时间】:2021-06-15 11:59:03
【问题描述】:

我正在尝试通过循环从 AWS S3 获取多个图像但我​​无法从该循环返回多个图像数据

获取单张图片

const getImage = async (imgKay) => {
    let tempImage = null;
    if (imgKay !== "default-header.jpg") {
       tempImage = await s3.getObject({Key: imgKay, Bucket: process.env.AWS_BUCKET_NAME}).promise();
    }
    return tempImage;
}

通过循环获取多个对象

const loopAllImageAndAddToList = (blockContent) => {
    console.log("Data fetching please wait");
    let imgList = new Array();
    blockContent.forEach(async (bc, bcIdx, arrNum) => {
        console.log("index: " + bcIdx + " Array Length: ", arrNum.length);
        if (bc.blockElement.name === "imgBlockContent") {
            const tempImage = await getImage(bc.blockElement.imgUrl);
            imgList.push({ key: bc.blockElement.imgUrl, binaryImg: tempImage.Body });
        }
    });


    return Promise.all(imgList);
}

快速获取请求

router.get('/preview/:id', (req, res, next) => {
    const sql = `SELECT id, title, bg_img, bg_color, link_color, layout, content, sibling FROM nodejs_story WHERE id=?`;

    conn.query(sql, [req.params.id], async (err, result, fields) => {
        if (err) throw err;
        try {
            const blockContent = await JSON.parse(result[0].content);
            const res = await loopAllImageAndAddToList(blockContent)
                console.log("res: ", res);
            res.render('template/template-preview', { docs: result[0] });
        } catch (readFileErr) {
            console.log("Read file error: ".red, readFileErr);
        }

    });
});

【问题讨论】:

  • 为什么不使用 loopAllImageAndAddToList() 的返回值?
  • 我试过这个仍然得到空白数组``` const res = await loopAllImageAndAddToList(blockContent) console.log("res: ", res); ```

标签: node.js amazon-web-services express amazon-s3 es6-promise


【解决方案1】:

这样就可以了

const loopAllImageAndAddToList = async () => {
    return Promise.all(imgKeys.map((img, index) => {
        console.log("Image: ", img);
        return getImage(img)
            .then(imgUrl => {
                // console.log("Returning from get image: ", imgUrl);
                return {
                    imgId: index + 1,
                    imgBfr: imgUrl
                }
            })
    }));

【讨论】:

  • 这种方式比 Mestre 的更好,因为您将获得多任务处理的好处,而他将按顺序解决 getImage() 承诺。您可能可以对其进行基准测试并查看,但这是一种非常惯用的方法。
  • 建议的解决方案没有考虑原始问题中似乎很重要的东西,条件if (bc.blockElement.name === "imgBlockContent") 无法通过直接映射实现。
【解决方案2】:

如果您希望并发(不是多任务处理)的性能而不是代码清晰度/简单性(这是我的第一个答案的重点),那么替代的更清晰的代码可能是这样的:

const loopAllImageAndAddToList = async (blockContent) => {
  const imgList = [];
  for (const bc of blockContent)
    if (bc.blockElement.name === "imgBlockContent")
      imgList.push(getImage(bc.blockElement.imgUrl)
       .then(temp => ({ key: bc.blockElement.imgUrl, binaryImg: temp.Body }))


  return Promise.all(imgList);
}

或者如果您喜欢链接代码并且不喜欢使用return 语句:

const loopAllImageAndAddToList = async (blockContent) => Promise.all(
  blockContent.reduce((imgList, bc) =>
    bc.blockElement.name !== 'imgBlockContent'
      ? imgList
      : imgList.concat(
        getImage(bc.blockElement.imgUrl)
          .then(temp => ({ key: bc.blockElement.imgUrl, binaryImg: temp.Body }))
      ), [])
)
      

【讨论】:

  • 我同意你的第一个答案。我认为这是更好的选择。我想做多任务处理。
【解决方案3】:

由于您使用的是 async/await,因此很容易继续使用它而不使用 Promise.all。只需将 forEach 替换为简单的 for 循环即可。

例如,您可以使用for of

const loopAllImageAndAddToList = (blockContent) => {
  console.log("Data fetching please wait");
  const imgList = new Array();
  for (const bc of blockContent) {
    if (bc.blockElement.name === "imgBlockContent") {
      const tempImage = await getImage(bc.blockElement.imgUrl);
      imgList.push({ key: bc.blockElement.imgUrl, binaryImg: tempImage.Body });
    }
  }


  return imgList;
}

【讨论】:

    猜你喜欢
    • 2020-12-14
    • 1970-01-01
    • 2017-10-24
    • 1970-01-01
    • 2018-07-02
    • 1970-01-01
    • 2022-01-03
    • 2018-06-30
    • 2023-01-24
    相关资源
    最近更新 更多