Обещание не разрешается с помощью асинхронного - PullRequest
0 голосов
/ 14 октября 2018

Я использую igmur api для загрузки изображений.Я написал приложение в Node.js, используя Promises, async-await.(обратите внимание, что я довольно новичок в этих понятиях).

Кажется, мой код работает.Он загружает изображения в 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
    })
})

Я следовал этому учебнику , в котором что-то похожее.

Ответы [ 3 ]

0 голосов
/ 14 октября 2018

(очень) более чистая и более производительная версия вашего кода будет выглядеть так:

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 для одновременного ожидания всех обещаний.

0 голосов
/ 14 октября 2018

Я вижу, по крайней мере, две проблемы:

  • Вы смешиваете асинхронное с обещанием, когда оно не нужно
  • Я подозреваю, 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,
  })
})
0 голосов
/ 14 октября 2018

Исправьте свою логику, чтобы проверять 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)
  }
}

По другой теме вам следуетвыйдите из цикла после ошибки, или вы можете в итоге вызвать reject, а затем разрешить, и это не хорошо.

...