Я использовал библиотеку Q kriskowal для проекта (веб-скрапер/симулятор человеческой деятельности) и познакомился с промисами, возвращая их и их разрешение/отклонение, а также базовые методы асинхронного потока управления библиотеки и механизмы выдачи/отлова ошибок оказались важными.
Однако я столкнулся с некоторыми проблемами. Мои promise.then
вызовы и мои обратные вызовы имеют сверхъестественную тенденцию образовывать пирамиды. Иногда это делается из соображений масштаба, а иногда — чтобы гарантировать определенный порядок событий. (Я полагаю, что смогу исправить некоторые из этих проблем с помощью рефакторинга, но в дальнейшем я хочу полностью избежать «ада обратных вызовов».)
Кроме того, отладка очень расстраивает. Я трачу много времени на то, чтобы console.log
найти источник ошибок и багов; после того, как я, наконец, найду их, я начну выбрасывать ошибки туда и ловить их где-то еще с помощью promise.finally
, но процесс обнаружения ошибок в первую очередь труден.
Кроме того, в моем проекте порядок имеет значение. Мне нужно сделать почти все последовательно. Часто я ловлю себя на том, что генерирую массивы функций, которые возвращают промисы, а затем связываю их друг с другом, используя Array.prototype.reduce
, что, как мне кажется, мне не нужно делать.
Вот пример одного из моих методов, который использует эту технику сокращения:
removeItem: function (itemId) {
var removeRegexp = new RegExp('\\/stock\\.php\\?remove=' + itemId);
return this.getPage('/stock.php')
.then(function (webpage) {
var
pageCount = 5,
promiseFunctions = [],
promiseSequence;
// Create an array of promise-yielding functions that can run sequentially.
_.times(pageCount, function (i) {
var promiseFunction = function () {
var
promise,
path;
if (i === 0) {
promise = Q(webpage);
} else {
path = '/stock.php?p=' + i;
promise = this.getPage(path);
}
return promise.then(function (webpage) {
var
removeMatch = webpage.match(removeRegexp),
removePath;
if (removeMatch !== null) {
removePath = removeitemMatch[0];
return this.getPage(removePath)
.delay(1000)
// Stop calling subsequent promises.
.thenResolve(true);
}
// Don't stop calling subsequent promises.
return false;
}.bind(this));
}.bind(this);
promiseFunctions.push(promiseFunction);
}, this);
// Resolve the promises sequentially but stop early if the item is found.
promiseSequence = promiseFunctions.reduce(function (soFar, promiseFunction, index) {
return soFar.then(function (stop) {
if (stop) {
return true;
} else {
return Q.delay(1000).then(promiseFunction);
}
});
}, Q());
return promiseSequence;
}.bind(this))
.fail(function (onRejected) {
console.log(onRejected);
});
},
У меня есть другие методы, которые делают в основном то же самое, но страдают от гораздо более серьезных проблем с отступами.
Я рассматриваю возможность рефакторинга моего проекта с использованием асинхронной библиотеки coalan. Это похоже на Q, но я хочу точно знать, чем они отличаются. У меня сложилось впечатление, что async более «ориентирован на обратный вызов», а Q - «ориентирован на обещания».
Вопрос. Учитывая мои проблемы и требования к проекту, что я выиграю и/или потеряю, используя асинхронность вместо Q? Как библиотеки сравниваются? (Особенно с точки зрения последовательного выполнения ряда задач и отладки/обработки ошибок?)
.series
и.eachSeries
. цепь .then может, конечно, достичь той же цели - person Kevin B   schedule 04.08.2014