承诺无法通过异步解决

时间:2018-10-14 13:03:05

标签: javascript node.js async-await es6-promise

我正在使用igmur api上传图像。我使用Promises(异步等待)在Node.js中编写了一个应用程序。 (请注意,我对这些概念还很陌生)。

我的代码似乎起作用了。它将图像上传到igmur。但是,问题是,诺言没有得到解决。请参考下面的代码。

router.post('/images/upload', async (req, res) => {
    /* we would receive a request of file paths as array */
    let filePaths = req.body.urls;

    let multipleUpload = new Promise(async (resolve, reject) => {
            let upload_len = filePaths.length,
                upload_res = new Array();

            for (let i = 0; i <= upload_len + 1; i++) {
                let filePath = filePaths[i];
                await imgur.upload(filePath, (error, result) => {
                    console.log(" A -> ");
                    if (upload_res.length === upload_len) {
                        console.log("******");
                        /* resolve promise after upload is complete */
                        resolve(upload_res)
                    } else if (result) {
                        /*push public_ids in an array */
                        console.log("OK")
                        upload_res.push(result.public_id);
                    } else if (error) {
                        console.log(error)
                        reject(error)
                    }

                })

            }
        })
        .then((result) => console.log(result))
        .catch((error) => error)

    let upload = await multipleUpload;
    res.json({
        'response': upload
    })
})

我遵循了这个here,它做了类似的事情。

3 个答案:

答案 0 :(得分:3)

我至少看到两个问题:

  • 在不需要时将异步与承诺混在一起
  • 我怀疑imgur.upload由于接受了回调函数而未返回Promise。

我认为这应该解决它:

router.post('/images/upload', async (req, res) => {
  let filePaths = req.body.urls
  let upload_len = filePaths.length
  let multipleUpload = filePaths.map(filePath => {
    return new Promise((resolve, reject) => {
      imgur.upload(filePath, (err, result) => {
        if (err) {
          reject(err)
        } else {
          resolve(result.public_id)
        }
      })
    })
  })

  let upload = await Promise.all(multipleUpload)

  res.json({
    response: upload,
  })
})

答案 1 :(得分:2)

一个(非常)干净,性能更高的代码版本是:

function uploadToImgur(filePath) {
    return new Promise((resolve, reject) => {
        imgur.upload(filePath, (err, res) => {
            if (err) reject(err);
            resolve(res.public_id);
        })
    })

}

router.post('/images/upload', async (req, res) => {
    /* we would receive a request of file paths as array */
    let filePaths = req.body.urls;
    let promises = filePaths.map(uploadToImgur);
    let upload = await Promise.all(promises);
    res.json({
        'response': upload
    })
})

这使用Array.map创建一个承诺数组,每个filePath对应一个承诺,然后使用Promise.all同时等待所有承诺。

答案 2 :(得分:1)

修正在推送length之后检查result的逻辑。您从不致电resolve

例如,如果收到1个文件,则将推入数组,然后退出循环。

if (result) {
  /*push public_ids in an array */
  console.log("OK")
  upload_res.push(result.public_id);

  if (upload_res.length === upload_len) {
    console.log("******");
    /* resolve promise after upload is complete */
    resolve(upload_res)
  }
}

关于另一个主题,您应该在发生错误后退出循环,否则您可能最终会调用拒绝,然后解决,这不好。