Я играю с написанием веб-службы с использованием Node.js/Express, которая генерирует некоторые объекты на основе шаблонов, а затем возвращает сгенерированные данные. Я использую обещания Bluebird для управления всей асинхронной логикой. После удаления всего ненужного мой код выглядит примерно так[1].
Моя проблема заключается в том, что основная логика может заблокироваться на несколько секунд, если запрошенное количество выходных элементов велико. Так как я играл с ES6 для этого проекта, моей первой мыслью было выделить создание элемента в генератор[2]. Однако единственный способ получить все результаты от этого генератора — это Array.from
, который не помогает с блокировкой.
Я играл с .map
, .all
, .coroutine
и парой других вещей, пытаясь асинхронно собрать результаты из генератора, но мне не повезло. Есть ли хороший способ сделать это с Bluebird? (Или, возможно, лучший способ сделать это вообще?)
Нативный ES6 Promise.all может принимать итератор и возвращать массив значений, но V8 еще не поддерживает это. Кроме того, в моих экспериментах с polyfills/Firefox он кажется синхронным.
Это не слишком распространенная операция, поэтому меня не волнует абсолютная производительность. Я просто хочу избежать блокировки очереди событий, и я бы предпочел красивое, легко читаемое и поддерживаемое решение.
[1]:
let Bluebird = require('bluebird');
let templates = ...; // logic to load data templates
function createRandomElementFromRandomTemplate(templates) {
let el;
// synchronous work that can take a couple of milliseconds...
return el;
};
api.createRandomElements = function(req, res) {
let numEls = req.params.numEls;
Bluebird.resolve(templates)
.then(templates => {
let elements = [];
// numEls could potentially be several thousand
for(let i = 0; i < numEls; ++i) {
elements.push(createRandomElementFromRandomTemplate(templates));
}
return elements;
})
.then(elements => {
res.json(elements);
})
.error(err => {
res.status(500).json(err);
});
}
[2]:
function* generateRandomElementsFromRandomTemplate(templates, numEls) {
for(let i = 0; i < numEls; ++i) {
let el;
// synchronous work that can take a couple of milliseconds...
yield el;
}
}
api.createRandomElements = function(req, res) {
let numEls = req.params.numEls;
Bluebird.resolve(templates)
.then(templates => {
// this still blocks
return Array.from(generateRandomElementsFromRandomTemplate(templates, numEls));
})
.then(elements => {
res.json(elements);
})
.error(err => {
res.status(500).json(err);
});
}
.each
может быть интересной. - person Benjamin Gruenbaum   schedule 16.01.2015