2014-12-28 3 views
0

Результат операции PUT против базы данных, иногда нормально, даже если он не возвращается как код HTTP 200.Bacon.js поток с некоторыми хорошими ошибками

В этом конкретном случае я хочу обрабатывать 400 как еще одну хорошую ошибку, но изо всех сил пытаюсь придумать элегантный способ сделать это.

# stream from a promise any non 200 is fail 
putter = Bacon.fromPromise @_exec 'PUT', '/some/resource', {} 
errors = putter.errors().mapError(errBody) # now errors are normal values 
badErrors = errors.filter(statusIsnt(400)).flatMap (body) -> 
    return new Bacon.Error body     # and now they are errors again 
okErrors = errors.filter(statusIs(400)).flatMap (body) -> {} 
noError = putter.mapError().filter (v) -> v? # attempt to get rid of errors 
Bacon.mergeAll noError, okErrors, badErrors # combine to get result stream 

Я родом из фона обещания, и я считаю, выше несколько неуклюжие, что приводит меня к выводу, что я что-то не хватает. Сравните:

@_exec 'PUT', '/some/resource', {} 
.fail (err) -> 
    if err.body.status == 400 # ok 
    return {} 
    else 
    throw err 
+0

Я думаю, что «лучший» ответ будет зависеть от того, что вы хотите сделать с результатом. Вы также можете посмотреть EventStream.subscribe, который получает все события, включая ошибки. Кроме того, я не думаю, что ваше сравнение справедливое, поскольку если бы все, что вы хотели сделать, это выбросить ошибки не 400, это было бы простое использование onError. – chreekat

+1

Справедливая точка. Это код инициализации. Я хочу делать вещи в зависимости от успеха или неудачи. Обещание, которое я мог бы в этот момент просто направить на '. Then', чтобы продолжить после init, то же самое с' .onValue' из 'mergeAll'. Оба 200 ответа (которые заканчиваются на 'noError'), и эти« правильные »ошибки должны дать мне точку для продолжения после init. –

ответ

1

Вы можете использовать withHandler с Bacon.Error для throw и (неявным) Bacon.Next для result. Но код будет очень похож на вашу обработку уже в обещании. На самом деле обедневная версия имеет меньше шаблонов.

Сравните свое обещание версию

promise = @_exec('PUT', '/some/resource', {}) 
recovered = promise.fail (err) -> 
    # 400 is ok. make it ok already in promise 
    if err?.body?.status == 400 then {} else throw err.body 
result = Bacon.fromPromise recovered 

и withHandler бекон «только» версии

promise = @_exec('PUT', '/some/resource', {}) 
stream = Bacon.fromPromise promise 
result = stream.withHandler (event) -> 
    if (event.hasValue()) 
    @push(event) 
    else 
    # error 
    if event.error?.body?.status == 400 then 
     @push({}) 
    else 
     @push(event) 
0

Одно из возможных решений для этого конкретного сценария, чтобы изменить результат уже в обещании, но я могу легко предусмотреть случаи, когда вы не можете сделать это.

Bacon.fromPromise @_exec('PUT', '/some/resource', {}).fail (err) -> 
    # 400 is ok. make it ok already in promise 
    if err?.body?.status == 400 then {} else throw err.body 

Должен быть лучший функциональный подход к этой проблеме?

0

withHandler является основным методом, который позволяет работать на событиях всех типов. В нем вы можете вызвать @push, который отправит ошибки в поток ошибок и значения в значение streeam. Возможно, следующее:

Bacon.fromPromise(@_exec('PUT', '/some/resource', {})) 
    .withHandler((event) -> 
     if event.isError && event.error.body?.status? == 400 
      @push(new Bacon.Next({})) 
     else 
      @push(event) 
    ) 
+0

Это выглядит почти точно, что я хочу, но он не работает должным образом. Возвращенный Bacon.Error переходит в поток * value *. 'Bacon.once (новый Bacon.Error ('fail')). MapError ((e) -> новый Bacon.Error (e)). Subscribe (e) -> console.log e' # как ожидалось: fail, 'Bacon.once (новый Bacon.Error ('fail')). mapError ((e) -> новый Bacon.Error (e)). onError (e) -> console.log e' # неожиданно:/nothing/ 'Bacon.once (новый Bacon.Error ('fail')). mapError ((e) -> новый Bacon.Error (e)). onValue (e) -> console.log e' # неожиданный: сбой –

+0

О, я понимаю. Похоже, Олег прав - вы хотите с Хандлером, хотя я думаю, что может быть более простая реализация. Я исправлю свой ответ. – chreekat

Смежные вопросы