Играя си с писането на уеб услуга, използвайки 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