【问题标题】:async await promises using loops in node使用节点中的循环异步等待承诺
【发布时间】:2021-10-03 10:25:34
【问题描述】:

在我开始之前,这完全是我没有完全理解 node / javascript 中异步编程的复杂性。

我有一个包含图像 URL 和输出名称的多维数组。我正在尝试使用sharp遍历它们、下载、操作和输出它们。我要做的是捕获任何形状作为错误抛出的损坏图像,更新数组并在任务完成后继续对数组进行处理。

我遇到的问题是我的代码没有等待集成完成,因此没有继续更新数组。

这是我正在使用的代码:

let imgArr = [['url1', 'url2', 'url3', 'url4'],['name1', 'name2', 'name3', 'name4']]

function saveImg(url, output)
    return new Promise(async(resolve, reject) => {
       axios.get(url, { responseType: 'arraybuffer' })
       .then((res) => {
          sharp(res.data)
          .resize({changing size etc})
          .png({quality: 95})
          .toFile(output)
          .then(() => { resolve() })
          .catch((err) => { reject() })
    })
}

function processImg(obj){
   return new Promise(async(resolve, reject) => {
      for(let i = 0; i < obj.length; i++){
         saveImg(obj[i][0], obj[i][1])
         .catch((err) => {
             imgArr[i][1] = 'image-not-found.png'
         })
      }
      resolve()
   })
 }

async function doStuff(){
     processImg(imgArr)
        .then(() => {
            console.log(imgArr) // this is where I'd hoped the updated array would appear
        })
        .catch((err) => {
            console.log(err)
        })
)

doStuff()

谢谢。

【问题讨论】:

  • 您希望各种saveImg 调用并行还是按顺序执行?
  • 您的代码存在多个问题。回到学习基础。 Stack Overflow 不是一所编码学校,也不是一个应该有人重写您的代码以使其正常工作的地方。不过我会给你一些提示: 1. 编写一个 async 函数,它一次处理一个图像并返回 axios.get(一个承诺) 2. 使用 Array.map,通过一个转换每个项目的函数映射你的数组进入一个承诺,作为对图像处理函数的一次调用 3. 通过Promise.allSettled 运行该承诺数组。 Promise.allSettled() 将在每个 Promise 被拒绝或解决后解决
  • @funkizer 是的,抱歉,这个问题有点含糊。我不是在任何人重写我的代码之后,我只需要掌握逻辑。你的回答很有用。必须承认,仅仅解决基本逻辑我真的很困惑。我要把它撕掉,然后按照你的建议重新开始。如果您将其发布为答案,我会标记它。谢谢。

标签: javascript node.js arrays promise


【解决方案1】:

当你像这样在for 循环中执行承诺时,它们都是并行开始的。然后在承诺实际解决之前立即致电resolve()

您可以使用 Promise.all(或 @funkizer 在 cmets 中建议的 Promise.allSettled)来解决此问题:

function processImg(obj){
   return new Promise(async(resolve, reject) => {
      Promise.allSettled(obj.map((item, i) =>
         saveImg(item[0], item[1])
         .catch((err) => {
             imgArr[i][1] = 'image-not-found.png'
         })
      )).then(resolve)
   })
 }

但是new Promise 中的这种包装是不必要的;你可以直接返回promise,如下:

function processImg(obj){
   return Promise.allSettled(obj.map((item, i) =>
      saveImg(item[0], item[1])
      .catch((err) => {
          imgArr[i][1] = 'image-not-found.png'
      })
   );
}

您可以类似地简化saveImg

function saveImg(url, output)
    return
       axios.get(url, { responseType: 'arraybuffer' })
       .then((res) =>
          sharp(res.data)
          .resize({changing size etc})
          .png({quality: 95})
          .toFile(output)
       );
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-11-01
    • 1970-01-01
    • 2017-06-15
    • 1970-01-01
    • 2018-08-13
    • 2019-12-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多