JavaScript цепочка обещаний: я изменяю размер изображения дважды, и express ответ становится неопределенным? - PullRequest
2 голосов
/ 13 января 2020

Если я изменю размер изображения дважды (используя библиотеку Sharp), мой маршрут возвращается неопределенным. Все мои измененные изображения отображаются. Это как-то, если дважды вызвать image.resize и .toBuffer(), это повредит объект res.

router.post('/submit', upload.single('file'), (req, res) => {
  var image = sharp(req.file.buffer)
  image.resize(1500, 1500, { fit: 'inside' }).toBuffer()
    .then(buffer => fs.writeFile('../image-md.jpg', buffer))
    .then(() => image.resize(500, 500, { fit: 'inside' }).toBuffer())
    .then(buffer => fs.writeFile('../image-sm.jpg', buffer))
    .then(() => res.json({ success: true })) 
    .catch(err => res.status(400).json({ error: err.message }))
})

// res is undefined, and no status is even returned

Странно то, что, если я закомментирую одно из размеров, все будет отлично работать:

router.post('/submit', upload.single('file'), (req, res) => {
  var image = sharp(req.file.buffer)
  image.resize(1500, 1500, { fit: 'inside' }).toBuffer()
    .then(buffer => fs.writeFile('../image-md.jpg', buffer))
    // .then(() => image.resize(500, 500, { fit: 'inside' }).toBuffer())
    // .then(buffer => fs.writeFile('../image-sm.jpg', buffer))
    .then(() => res.json({ success: true })) 
    .catch(err => res.status(400).json({ error: err.message }))
})

// res.data is { success: true } and status 200 is returned

Помогите!

Ответы [ 2 ]

0 голосов
/ 13 января 2020

Вопрос оказался мой запрос тайм-аут. 100

Мой тайм-аут был установлен на 1 секунду, и когда я выполнял более одной операции изменения размера, это занимало больше 1 секунды. Я увеличил время ожидания до 10 секунд, и это исправило его.

0 голосов
/ 13 января 2020

Основная проблема здесь:

.then(() => image.resize(500, 500, { fit: 'inside' }).toBuffer())

.then должен принимать только функцию в качестве параметра, но вы передаете результат вызова toBuffer on вызова image.resize немедленно. Использование скобок для облегчения понимания группировки:

.then(
  (() => image.resize(500, 500, { fit: 'inside' }))
    .toBuffer()
)

Не на 100% уверен насчет соглашений здесь, но читатель кода (как я) будет , вероятно, , за исключением ссылки на fs для ссылки на встроенный модуль fs, чей метод writeFile не возвращает Promise, так что использование .then или await на нем может привести к путанице - вы можете подумать, что он назвал его что-то вроде fsPromises, или что-то похожее (только не fs).

Возможно, было бы легче читать, используя async / await:

const processImage = async (requestBuffer) => {
  const image = sharp(requestBuffer);
  const bigBuffer = await image.resize(1500, 1500, { fit: 'inside' }).toBuffer();
  await fsPromises.writeFile('../image-md.jpg', bigBuffer);
  const smallBuffer = await image.resize(500, 500, { fit: 'inside' }).toBuffer();
  await fsPromises.writeFile('../image-sm.jpg', smallBuffer);
};

router.post('/submit', upload.single('file'), (req, res) => {
  processImage(req.file.buffer)
    .then(() => {
      res.json({ success: true });
    })
    .catch((err) => {
      res.status(400).json({ error: err.message })
    });
});
...