Да, обещания - это асинхронные обратные вызовы. Они не могут делать ничего, что не могут сделать обратные вызовы, и вы сталкиваетесь с теми же проблемами с асинхронностью, что и с обычными обратными вызовами.
Однако, обещания больше , чем просто обратные вызовы. Они - очень мощная абстракция, обеспечивают более чистый и улучшенный функциональный код с менее склонным к ошибкам шаблоном.
Итак, в чем главная идея?
blockquote>Обещания объекты, представляющие результат одного (асинхронного) вычисления. Они разрешают этот результат только один раз. Есть несколько вещей, что это означает:
Обещает реализовать шаблон наблюдателя:
- Вам не нужно знать обратные вызовы, которые будут использовать значение до завершения задачи.
- Вместо того, чтобы ожидать обратных вызовов в качестве аргументов для ваших функций, вы можете легко
return
объект Promise- Обещание сохранит это значение, и вы можете прозрачно добавьте обратный вызов, когда захотите. Он будет вызываться, когда результат будет доступен. «Transparency» подразумевает, что когда у вас есть обещание и добавление обратного вызова к нему, для вашего кода не имеет значения, достиг ли результат: API и контракты одинаковы, что упрощает кэширование / memoisation.
- Вы можете легко добавить несколько обратных вызовов
Обещания связаны с цепью ( monadic , если хотите):
- Если вам нужно преобразовать значение, представляемое обещанием, вы map преобразуете функцию над обещанием и получите новое обещание, которое представляет преобразованный результат. Вы не можете синхронно получить значение, чтобы использовать его каким-то образом, но вы можете легко снять преобразование в контексте обещания. Нет обратных вызовов шаблонов.
- Если вы хотите связать две асинхронные задачи, вы можете использовать метод
.then()
.Звучит сложно? Ответ на этот вопрос будет вызван первым результатом и даст обещание получить обещание вернуться. Время для примера кода.
var p1 = api1(); // returning a promise var p3 = p1.then(function(api1Result) { var p2 = api2(); // returning a promise return p2; // The result of p2 … }); // … becomes the result of p3 // So it does not make a difference whether you write api1().then(function(api1Result) { return api2().then(console.log) }) // or the flattened version api1().then(function(api1Result) { return api2(); }).then(console.log)
Сглаживание не приходит волшебным образом, но вы можете легко это сделать. Для вашего сильно вложенного примера эквивалент (ближайший) будет
api1().then(api2).then(api3).then(/* do-work-callback */);
. Если просмотр кода этих методов помогает понять, - это самое основное обещание lib в нескольких строках .
Что представляет собой большая проблема с обещаниями?
blockquote>Абстракция Promise позволяет значительно улучшить компоновку функций. Например, рядом с
then
для цепочки функцияall
создает обещание для комбинированного результата нескольких обещаний с параллельным ожиданием.И последнее, но не менее важное: обещания с интегрированной обработкой ошибок. Результатом вычисления может быть то, что либо обещание выполнено со значением, либо отклонено с причиной. Все функции композиции обрабатывают это автоматически и распространяют ошибки в цепочках обещаний, так что вам не нужно заботиться об этом явно везде - в отличие от реализации простого обратного вызова. В конце вы можете добавить выделенный обратный вызов ошибки для всех произошедших исключений.
Не говоря уже о необходимости конвертировать вещи в обещания.
blockquote>Это довольно тривиально на самом деле с хорошими библиотеками обещаний, см. Как мне преобразовать существующий API обратного вызова в обещания?
ОБНОВЛЕНИЕ : После этого ответа я бы теперь изменил свой ответ на использование зефира / зефира-sqlalchemy.
Предыдущий ответ:
Я не знаю ответа наверняка, но ...
Из издания Мигеля Гринберга Flask Web Development, 2-е издание, стр. 210-213, он применяет подход, согласно которому метод
def Post(db.Model):
# ...
def to_json(self):
json_post = {
** json using model **
}
return json_post
определен в models.py