Обещание разрешить пожары до завершения задачи

Я использую функцию обещания и Jimp, чтобы изменить размер изображения, сохранить его в папке, а затем вернуть путь к новому изображению с измененным размером.

Однако функция resolve() в resizeWidth() запускается до выполнения image.resize().write(), что означает сбой моего приложения, поскольку оно не может найти новый файл.

Любая помощь будет принята с благодарностью.

const fs = require('fs');
const path = require('path');
const jimp = require('jimp');

const resizeWidth = function(file, width) {
  return new Promise((resolve, reject) => {
    jimp.read(path.join(__dirname, '..', 'assets', 'images', file), (err, image) => {
      if (err) reject(err);
      const xSize = parseInt(width);
      image.resize(xSize, jimp.AUTO)
        .write(path.join(__dirname, '..', 'assets', 'images', 'tmp', file));
      resolve(path.join(__dirname, '..', 'assets', 'images', 'tmp', file));
    });
  });
};

module.exports = function(server) {
  server.get('/images/:name/:width', (req, res) => {
    resizeWidth(req.params.name, req.params.width)
      .then(() => {
        fs.readFile(path.join(__dirname, '..', 'assets', 'images', 'tmp', req.params.name),
          (err, newData) => {
            if (err) throw err;
            res.sendRaw(200, newData, {
              'Content-Length': Buffer.byteLength(newData)
            });
            res.end();
          });
      })
      .catch((err) => {
        console.log(err);
      });
  });
};


person Brian Emilius    schedule 14.08.2017    source источник
comment
Вы можете просто сделать path.join(__dirname, '../assets/images/tmp', file), заметьте. Также обратите внимание, что throw err убьет ваш сервер; Я бы предложил использовать обещанную версию fs.readFile.   -  person Ry-♦    schedule 14.08.2017
comment
@ Райан, да, это всего лишь предварительный тест, чтобы увидеть, соответствует ли jimp требованиям проекта - рефакторинг позаботится о вещах, которые вы упомянули.   -  person Brian Emilius    schedule 14.08.2017
comment
Да, и определенно не читайте и не отвечайте содержимым path.join(…, 'tmp', req.params.name) без проверки или преобразования req.params.name, если только вы не хотите, чтобы клиенты имели доступ для чтения/записи (в зависимости от разрешений — оба одинаково плохи) к любому файлу в вашей системе с ?name=../../sensitive-config. Я рекомендую UUID или хэш.   -  person Ry-♦    schedule 14.08.2017


Ответы (1)


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

jimp.read(path.join(__dirname, '..', 'assets', 'images', file), (err, image) => {
  if (err) reject(err);
  const xSize = parseInt(width);
  image.resize(xSize, jimp.AUTO)
    .write(path.join(__dirname, '..', 'assets', 'images', 'tmp', file), () => {
       resolve(path.join(__dirname, '..', 'assets', 'images', 'tmp', file));
    });
});
person ZeroCho    schedule 14.08.2017
comment
До смешного простое решение. Благодарю вас! - person Brian Emilius; 14.08.2017
comment
@BrianEmilius Если это сработает, примите этот ответ. Если нет, прокомментируйте этот ответ, какая еще проблема возникает. Я постараюсь помочь. - person ZeroCho; 14.08.2017