admin管理员组

文章数量:1401199

I'm working on a Discord bot that takes an uploaded picture attachment, saves it to a temporary file after editing, and then uploads it to the Discord server. Everything works, except for the timing. The sendImage function gets called after the generateImagePixel function, but tries to upload the temp image before jimp.write is finished, causing an ENOENT error. How would I fix my timing issue?

client.on('message', message => {
    if (message.content.includes(config.prefix + 'pixel')) {
        var tempname = d.getTime();
        console.log(tempname);
        generateImagePixel(message.attachments, tempname).then(() => sendImage(tempname, message))
    }
});

function generateImagePixel(msg, name) {
    return new Promise((resolve, reject) => {
        msg.forEach(a => {
            try {
                jimp.read(a.url, function (err, image) {
                    const clone = image.clone();
                    clone.pixelate(8)
                    .rgba(true)
                    .filterType(0)         
                    .write('./temp/' + name + '.png');
                });
            } catch(err) {
                 console.log(err);
            }
        });
        resolve(name)
    })
}

function sendImage(tempname, msg) {
    msg.channel.send({
        file: './temp/'+ tempname + '.png' // Or replace with FileOptions object
    });
}

I'm working on a Discord bot that takes an uploaded picture attachment, saves it to a temporary file after editing, and then uploads it to the Discord server. Everything works, except for the timing. The sendImage function gets called after the generateImagePixel function, but tries to upload the temp image before jimp.write is finished, causing an ENOENT error. How would I fix my timing issue?

client.on('message', message => {
    if (message.content.includes(config.prefix + 'pixel')) {
        var tempname = d.getTime();
        console.log(tempname);
        generateImagePixel(message.attachments, tempname).then(() => sendImage(tempname, message))
    }
});

function generateImagePixel(msg, name) {
    return new Promise((resolve, reject) => {
        msg.forEach(a => {
            try {
                jimp.read(a.url, function (err, image) {
                    const clone = image.clone();
                    clone.pixelate(8)
                    .rgba(true)
                    .filterType(0)         
                    .write('./temp/' + name + '.png');
                });
            } catch(err) {
                 console.log(err);
            }
        });
        resolve(name)
    })
}

function sendImage(tempname, msg) {
    msg.channel.send({
        file: './temp/'+ tempname + '.png' // Or replace with FileOptions object
    });
}
Share Improve this question asked Jul 20, 2018 at 7:50 Gman0064Gman0064 1073 silver badges13 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 6

This is a typical example of executing asynchronous functions in a synchronous loop.

jimp.read is asycnhronous, so each call returns immediately before the actual stuff it does finishes. Therefore msg.forEach also finishes before jimp is done.

Once you are using something asynchronous, all you do has to be in asynchronous style:

function generateImagePixel(msg, name) {
  const promises = msg.map(attachment => {
    return jimp.read(attachment.url)
      .then(image => {
        return image
          .pixelate(8)
          .rgba(true)
          .filterType(0)         
          .write('./temp/' + name + '.png');
      })
      .catch(console.error);
  });

  return Promise.all(promises)
    .then(() => name);
}

本文标签: javascriptNodejs AsyncPromise explanation with JIMPStack Overflow