Для произвольной реализации обещания отложенный шаблон (не путать с antipattern) может выглядеть так:
const deferred = new Deferred;
...
// scopes where `deferred` object reference was passed before promise settlement
deferred.promise.then((result) => { ... }, (error) => { ... });
...
deferred.resolve(...);
// doesn't affect promise state
deferred.reject();
...
// after promise settlement
deferred.promise.then((result) => { ... }, (error) => { ... });
Объект deferred
имеет нерегулярное обещание, которое может быть передано в другие области функций по ссылке. Все цепочки обещаний будут выполняться по договоренности с обещаниями, неважно, было ли deferred.promise
до привязки с then
или после. Состояние обещания не может быть изменено после его урегулирования.
Как следует из ответа, исходные варианты: ReplaySubject
и AsyncSubject
.
Для данной настройки (демо)
var subject = new Rx.AsyncSubject;
var deferred = subject.first();
deferred.subscribe(
console.log.bind(console, 'Early result'),
console.log.bind(console, 'Early error')
);
setTimeout(() => {
deferred.subscribe(
console.log.bind(console, 'Late result'),
console.log.bind(console, 'Late error')
);
});
Это приводит к желаемому поведению:
subject.error('one');
subject.next('two');
Ранняя ошибка
Поздняя ошибка 1
Это приводит к нежелательному поведению:
subject.error('one');
subject.next('two');
subject.complete();
Ранняя ошибка
Поздний результат два
Это приводит к нежелательному поведению:
subject.next('two');
subject.complete();
subject.next('three');
Ранний результат два
Поздний результат три
Результаты от ReplaySubject
отличаются, но все же не соответствуют ожидаемым результатам. next
и error
ошибки обрабатываются отдельно, а complete
не мешает наблюдателям получать новые данные. Это может работать для одиночного next
/error
, проблема в том, что next
или error
можно вызвать несколько раз непреднамеренно.
Причина использования first()
заключается в том, что subscribe
являются одноразовыми подписками, и я хотел бы удалить их, чтобы избежать утечек.
Как это должно быть реализовано с помощью наблюдаемых RxJS?