Я использую библиотеку Q в nodejs и не слишком много работал с обещаниями в прошлом, но у меня есть полупростая логика, требующая много гнездования, и мысль Q будет хорошим решением , однако я нахожу, что он кажется почти таким же, как просто «callback hell».Использование Q/обещаний против обратных вызовов
В основном я говорю 5 методов, все из которых требуют данных из предыдущего или одного из предыдущих. Вот пример:
Начнем с некоторых двоичных данных, которые имеют хэш-файл sha1, сгенерированный на основе двоичного кода.
var data = {
hash : "XXX"
, binary: ''
}
Во-первых, мы хотим, чтобы увидеть, если у нас уже есть это, используя этот метод:
findItemByHash(hash)
Если мы не имеем, мы должны сохранить его, используя:
saveItem(hash)
Теперь нам нужно связать это с пользователем, но не только с результатами сохранения. Там сейчас гораздо больше иерархии, которую мы связываем, поэтому нам нужно получить, что первый, делая:
getItemHierarchy(item_id)
, мы используем item_id
вернулся из наших предыдущих saveItem
Теперь мы можем «копировать» эти результаты к пользователь:
saveUserHierarchy(hierarchy)
Теперь мы сделали, однако, это предполагает, что товар еще не существовало. Поэтому нам нужно обработать случай, когда элемент действительно существует. Это было бы:
Нам нужно проверить, если пользователь может aleady иметь это:
getUserItemByItemId(item_id)
- item_id был возвращен из findItemByHash
Если он существует, мы сделали.
Если нет:
getItemHierarchy(item_id)
Тогда
saveUserHierarchy(hierarchy)
Итак, теперь у нас есть обратные вызовы, которые делают эти проверки, и это хорошо. Но нам нужно обрабатывать ошибки в каждом случае на этом пути. Это тоже хорошо, просто добавляет в беспорядок. Действительно, если какая-либо часть потока выдает ошибку или отклоняет, то она может остановиться и просто обрабатывать ее в одном месте.
Теперь с Q, мы могли бы сделать что-то вроде этого:
findItemByHash(hash).then(function(res) {
if (!res) {
return saveItem(hash).then(function(item) {
return getItemHierarchy(item.id).then(function(hierarchy) {
return saveUserHierarchy(hierarchy);
});
})
} else {
return getUserItemByItemId(res.id).then(function(user_item) {
if (user_item) {
return user_item;
}
return getItemHierarchy(res.id).then(function(hierarchy) {
return saveUserHierarchy(hierarchy);
});
});
}
})
//I think this will only handle the reject for findItemByHash?
.fail(function(err) {
console.log(err);
})
.done();
Так что, я думаю, мой вопрос заключается в следующем. Есть ли лучшие способы справиться с этим в Q?
Спасибо!
В приведенном коде есть возможная ошибка. Ваша вторая 'getItemHierarchy' использует' item.id' вместо 'user_item.id'. Работая над ответом - просто подумал, что я укажу, что в то же время ;-) –
Ах, на самом деле это должно быть использование 'res.id' – dzm