【问题标题】:Promise is resolving before block of code is finishedPromise 在代码块完成之前解决
【发布时间】:2020-02-19 06:17:25
【问题描述】:

我正在使用 Jimp 创建图像。在执行下一个代码块之前,我需要等到所有图像都创建完成。

这是我的脚本和服务器代码:

   //server.js
    var exportImages = () => {
      ImageProcessor.createImage(
        request.body.templatePath,
        request.body.bitPath,
        request.body.exportPath
      ).then((msg) => {
        console.log("In the final then block");
        response.send(msg);
      }).catch((err) => {
        response.send(err.message)
      });
    }

    exportImages();

处理器.js

createImage: (templatePath, bitPath, activePath) => {

var jimpBit = new Jimp(bitPath, function(err, img) {
  err ? console.log("error loading bit: " + err) : console.log("Bit loaded");
});

let randomId = Math.floor(Math.random() * 100000) + 1; // # 1-100000
activePath = './active/' + randomId + '/';

return new Promise( (resolve, reject) => {
  fsPromises.readdir(templatePath)
    .then( (templateImages ) => {

      templateImages.forEach( (templateImage, index) => {
        templateImage = './raw/template1/' + templateImage;
        var activeImage = activePath + randomId + '-' + index + '.PNG';

        Jimp.read(templateImage)
          .then( (template) => (template.clone().write(activeImage)))

          .then( () => (Jimp.read(activeImage)))

          .then( (temporaryImage) => {
            temporaryImage
              .composite( jimpBit, 50, 50 )
              .composite( jimpBit, 150, 150 )
              .write(activeImage);
            console.log("Wrote image: " + activeImage);
          })

          .catch( (err) => {
            reject("Error with Jimp: " + err.message);
          });
      });
    })
    .then( () => {
      resolve(activePath);
    })
    .catch( (err) => {
      reject("Error reading files from " + templatePath + "\n" + err.message);
    })
});

有人可以帮我理解为什么在创建图像之前调用最后一个 .then 块吗?

我的实际结果是:

In the final then block
Bit loaded
Created image: ./active/64136/64136-4.PNG
Created image: ./active/64136/64136-2.PNG
Created image: ./active/64136/64136-6.PNG
Created image: ./active/64136/64136-1.PNG
Created image: ./active/64136/64136-7.PNG
Created image: ./active/64136/64136-5.PNG
Created image: ./active/64136/64136-0.PNG
Created image: ./active/64136/64136-3.PNG

【问题讨论】:

  • 使用 Promise.all 代替 forEach 并在 Promise.all 返回响应后解决一个承诺。
  • 一个想法:将.forEach 更改为常规的for 循环并在教学中的异步操作上使用await。现在的问题是.forEach() 不等待内部的任何承诺,因此它在循环内的任何承诺完成之前很久就完成了循环,因此您调用resolve() 太快了。您也不需要将其包装在 new Promise() 中,因为只要将内部承诺添加到链中,您就可以返回已有的承诺链。
  • 你为什么要构造一个 Promise,而它内部调用的函数返回一个 Promise?

标签: javascript node.js promise fs


【解决方案1】:

首先,.forEach 中的 Promise 永远不会等待

其次,你构造一个新的 Promise,当 Promise 执行器内部调用的函数返回一个 Promise - 这是一个反模式

以下内容应该适合您

createImage: (templatePath, bitPath, activePath) => {

    var jimpBit = new Jimp(bitPath, (err, img) => err ? console.log("error loading bit: " + err) : console.log("Bit loaded"));

    let randomId = Math.floor(Math.random() * 100000) + 1;
    activePath = './active/' + randomId + '/';

    return fsPromises.readdir(templatePath)
    .then((templateImages) => Promise.all(templateImages.map((templateImage, index) => {
        templateImage = './raw/template1/' + templateImage;
        var activeImage = activePath + randomId + '-' + index + '.PNG';

        return Jimp.read(templateImage)
        .then((template) => (template.clone().write(activeImage)))
        .then(() => (Jimp.read(activeImage)))
        .then((temporaryImage) => temporaryImage
            .composite(jimpBit, 50, 50)
            .composite(jimpBit, 150, 150)
            .writeAsync(activeImage) // *** writeAsync ***
        ).then(() => console.log("Wrote image: " + activeImage))
        .catch((err) => {
            throw "Error with Jimp: " + err.message;
        });
    })))
    .then(() => activePath)
    .catch((err) => {
        throw "Error reading files from " + templatePath + "\n" + err.message;
    });
}

【讨论】:

  • 我仍然得到相同的输出(在创建图像之前达到最终然后阻塞)。调用函数时没有任何变化,对吗?
  • @raney24 抱歉,我可能错过了一次回报 - 在我尝试修复它之前,temporaryImage .composite(jimpBit, 50, 50) .composite(jimpBit, 150, 150) .write(activeImage) 是否会返回一个 Promise?它甚至是异步的吗?
  • 我现在明白了......如果你使用 .writeAsync 而不是 .write 它会返回一个 Promise - 现在应该很好了
  • @raney24 - 不,它不应该......事实上我的版本正确返回activePath - 你的将是一个语法错误......查看concise arrow body的文档
猜你喜欢
  • 2018-04-28
  • 1970-01-01
  • 2019-03-31
  • 2018-07-07
  • 2019-08-13
  • 1970-01-01
  • 1970-01-01
  • 2019-03-07
  • 1970-01-01
相关资源
最近更新 更多