Занимаюсь изучением Node и решил начать с koa.
Сейчас пытаюсь решить следующую задачу: нужно реализовать импорт xlsx файла в БД.
Загрузку и чтение файла я реализовал, в процессе импорта нужно добавить проверку корректности данных через доп. запросы к БД и вот здесь возникает сложность. Не могу сообразить как сделать запросы к БД псевдо-синхронными.
Т.е. поэтапно у меня получается следующее:
1. файл загружается на сервер
2. происходит чтение файла
3. через array.map для каждой записи из файла вызывается функция для валидации
4. внутри функции валидации нужно сделать запрос к БД, после выполнения которого продолжить выполнение валидации. И в этом месте загвоздка, т.к. запрос к БД выполняется позже выполнения основного кода.
Пример кода:
function *importExcel() {
// https://github.com/cojs/busboy
const parse = require('co-busboy');
const fs = require('fs');
const path = require('path');
const config = require('../../config/path');
const xlsx = require('xlsx');
// multipart upload
let parts = parse(this, {
checkFile: function (fieldname, file, filename) {
let ext = path.extname(filename);
if (ext !== '.xlsx' && ext !== '.xlsm') {
let err = new Error('Файл должен иметь расширение xlsx либо xlsm');
err.status = 400;
return err;
}
}
});
let part = yield parts;
let stream = fs.createWriteStream(path.join(config.tmp, Math.random().toString()));
part.pipe(stream);
let workBook = yield function (done) {
stream.on('close', function () {
try {
let workBook = xlsx.readFileSync(stream.path);
done(null, workBook);
} catch (err) {
done(err);
}
});
};
let sheetName = workBook.SheetNames[0];
let workSheet = workBook.Sheets[sheetName];
let rows = xlsx.utils.sheet_to_json(workSheet);
if (rows.length == 0) {
throw new Error('Импортируемый файл пуст');
}
let messages = rows.map((item) => {
if (Object.keys(item).length > 1) {
try {
// ВЫЗОВ ФУНКЦИИ ДЛЯ ПРОВЕРКИ ДАННЫХ В СТРОКЕ ФАЙЛА
return validateForImport(item);
} catch (err) {
return err.message;
}
}
return true;
}).filter((item) => item !== true);
this.body = {
success: true,
error: messages,
};
this.type = 'application/json';
}
/**
* Валидация для импорта
*
* @param data
* @returns {boolean}
*/
function validateForImport(data) {
const requiredFields = ['#', 'CID', 'PID', 'Производитель', 'Модель', 'Тип оборудования'];
requiredFields.forEach((field) => {
if (data[field] == undefined) {
let index = field !== '#' ? data['#'] + ': ' : '';
throw new Error(index + 'колонка "' + field + '" не заполнена');
}
});
let keys = Object.keys(data);
keys.forEach((field) => {
data[field] = data[field].trim();
});
let deviceType;
// в этом месте нужно сделать запрос к БД и после его выполнения продолжить дальше выполнять функцию
// выдает ошибку: <b>SyntaxError: Unexpected strict mode reserved word</b>
// let deviceType = yield db.type.findOne({where: {name: data['Тип оборудования']}});
// в этом случае данные из БД приходят после отдачи ответа в браузер
// co(function*() {
// return yield db.type.findOne({where: {name: data['Тип оборудования']}});
// }).then(function (value) {
// console.log(value);
// });
if (!deviceType) {
throw new Error(data['#'] + ': тип обородувания "' + data['Тип оборудования'] + '" не найден');
}
}
Подскажите как грамотнее решить эту задачу.
p.s. используется фреймворк koa и sequelizer для работы с mysql