Обработка загрузки файла внутри рабочего потока в node.js - PullRequest
1 голос
/ 04 октября 2019

У меня есть API загрузки POST /api/v1/upload, где пользователи могут загружать текстовые файлы. Я использовал Node Formidable для анализа данных формы в Express, и все работает хорошо. Вот текущий код.

// app.js

...
const IncomingForm = require('formidable').IncomingForm;
app.post('/api/v1/upload', (req, res) => {
  const form = new IncomingForm();
  form.on('file', async (field, file) => {
    // do something...
  });
  form.on('end', () => {
    console.log('Done parsing.');
  });
  form.parse(req); // I believe this is the main function
})
...

Теперь я хочу делегировать эту операцию рабочему потоку.

// app.js

...
const usingWorkerThreads = require('./worker.js')
router.post('/api/v1/upload', (req, res) => {
  const result = await usingWorkerThreads(req);
  res.send(result);
});
...

А вот мой стандартный файл worker_thread, довольно стандартный, взято с официального сайта node.js .

// worker.js

...
const IncomingForm = require('formidable').IncomingForm;
const {
  Worker, isMainThread, parentPort, workerData
} = require('worker_threads');

if (isMainThread) {
  module.exports = function parseJSAsync(script) {
    return new Promise((resolve, reject) => {
      const worker = new Worker(__filename, {
        workerData: script
      });
      worker.on('message', resolve);
      worker.on('error', reject);
      worker.on('exit', (code) => {
        if (code !== 0)
          reject(new Error(`Worker stopped with exit code ${code}`));
      });
    });
  };
} else {
  // Form-parsing code, taken out from app.js and pasted here
  const form = new IncomingForm();
  form.on('file', async (field, file) => {
    // do something...
  });
  form.on('end', () => {
    parentPort.postMessage('Done parsing.')
  });
  form.parse(workerData);
}
...

Проблема в том, что объект req нельзя передать из app.js в worker.js, а для библиотеки Formidable требуется req объект. Вот ошибка, которую я получаю.

(node:13024) UnhandledPromiseRejectionWarning: DataCloneError: function resetHeadersTimeoutOnReqEnd() {
  debug('resetHeadersTimeoutOnReqEnd');

  const parser = this.socket....<omitted>...
} could not be cloned.
    at new Worker (internal/worker.js:305:17)

Похоже, что есть функция с именем resetHeadersTimeoutOnReqEnd() где-то глубоко вложенная в объект req, который не может быть клонирован при передаче в worker.js. Даже если я вручную найду и удалю эту функцию из объекта req, есть еще одна похожая функция, которая вызывает ту же проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...