2016-12-13 2 views
1

Я вижу документы для Bluebird's finally, но я до сих пор не совсем понимаю разницу против then.В чем разница между тем и, наконец, в обещании?

Должно быть ясным: я точно знаю, почему then вызывается после catch. I хочу это будет называться после улова. Это намерение. Мой вопрос: Если я хочу код всегда должен выполняться независимо от состояния обещания, в чем разница между then и finally для этого?

Я построил этот тест:

var Promise = require("bluebird"); 

function test1() { 
    console.log("RESOLVE + THEN + CATCH + THEN"); 
    return new Promise((resolve, reject) => resolve()) 
     .then(() => console.log("then")) 
     .catch(err => console.log("error:", err.message)) 
     .then(() => console.log("end")); 
} 

function test2() { 
    console.log("REJECT + THEN + CATCH + THEN"); 
    return new Promise((resolve, reject) => reject(new Error("rejected"))) 
     .then(() => console.log("then")) 
     .catch(err => console.log("error:", err.message)) 
     .then(() => console.log("end")); 
} 

function test3() { 
    console.log("RESOLVE + THEN + CATCH + FINALLY"); 
    return new Promise((resolve, reject) => resolve()) 
     .then(() => console.log("then")) 
     .catch(err => console.log("error:", err.message)) 
     .finally(() => console.log("end")); 
} 

function test4() { 
    console.log("REJECT + THEN + CATCH + FINALLY"); 
    return new Promise((resolve, reject) => reject(new Error("rejected"))) 
     .then(() => console.log("then")) 
     .catch(err => console.log("error:", err.message)) 
     .finally(() => console.log("end")); 
} 

// run tests "sequentially" so console output doesn't get blended 
setTimeout(test1, 500); 
setTimeout(test2, 1000); 
setTimeout(test3, 1500); 
setTimeout(test4, 2000); 

Это тестирует четыре случая:

  1. .then(...).catch(...).then(...) с разрешенным обещанием.
  2. .then(...).catch(...).then(...) с отклоненным обещанием.
  3. .then(...).catch(...).finally(...) с разрешенным обещанием.
  4. .then(...).catch(...).finally(...) с отклоненным обещанием.

Результаты, которые я вижу, являются случаи 1 + 2 ведет себя идентично 3 + 4: Последний бит (then или finally в зависимости от теста) не выполняется независимо от того, что происходит перед ним, как и предполагалось. Вывод этой программы:

RESOLVE + THEN + CATCH + THEN 
then 
end 
REJECT + THEN + CATCH + THEN 
error: rejected 
end 
RESOLVE + THEN + CATCH + FINALLY 
then 
end 
REJECT + THEN + CATCH + FINALLY 
error: rejected 
end 

Теперь, почему я спрашиваю, потому что я видел comment on this other question I asked:

Не уверен, что если ваши обещания поддержать его, но вы должны изменить последние .then до .finally, так что busy всегда очищается.

С моей очень ограниченным знанием then и выше испытаний, похоже, then достаточно. Но после этого комментария я спрашиваю себя и безопасность использования then для выполнения кода «finally».

Так что мой вопрос: В чем разница между then и finally? Они смотрят как они ведут себя одинаково, но когда мне нужно будет использовать finally вместо then?

+0

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

+0

@KevinB Нет, совсем нет. Я точно знаю, почему 'then' вызывается после' catch'. Я хочу, чтобы он был вызван после улова. Я спрашиваю: если я * хочу * код всегда выполняться независимо от состояния обещания, в чем разница между 'then' vs' finally' для этого? –

+1

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

ответ

3

Первое отличие: иногда вы не хотите ломать ошибки в месте, которое они возникают, но в коде, который использует эту функцию, поэтому вы не поймаете их. В этом случае вы не можете заменить then() и finally().

Иногда вам нужно что-то убрать, была ли ошибка или нет (обнуление ссылок, сброс тайм-аутов ... таких вещей). Вот где вы используете finally().

Второе отличие: функция, которую вы передаете catch(), также может быть брошена, тогда у вас будет отклоненное обещание, и следующее then() не будет называться.

(так, наконец, до того, как улов будет по-прежнему выполнять на ошибку, не знал, что)

Да, это точка finally(). Он будет выполнен при любых обстоятельствах без изменения разрешенного значения.

Возможно, вы захотите прочитать/google немного о try {} finally {}, без улова.

0

Хорошо, после некоторых бесед и много помощи от KevinB, я выяснил хотя бы одно различие. Рассмотрим следующие два новых теста:

function test5() { 
    console.log("REJECT + THEN + CATCH/THROW + THEN"); 
    return new Promise((resolve, reject) => reject(new Error("rejected"))) 
     .then(() => console.log("then")) 
     .catch(function(err) { throw new Error("error in catch"); }) 
     .then(() => console.log("end")); 
} 

function test6() { 
    console.log("REJECT + THEN + CATCH/THROW + FINALLY"); 
    return new Promise((resolve, reject) => reject(new Error("rejected"))) 
     .then(() => console.log("then")) 
     .catch(function(err) { throw new Error("error in catch"); }) 
     .finally(() => console.log("end")); 
} 

В этих обещание отвергается, но ошибка генерируется из catch.

Обещание в конечном итоге отменяется в обоих случаях, но для finally корпус finally по-прежнему выполнен, then нет.

So это разница. Они почти то же самое с единственным исключением, что при ошибке вызывается из catch обработчик, finally выполняет, а then - нет.

Это означает, что комментарий, который я цитировал, также имеет свои достоинства. Если в моем обработчике ошибок произошла другая ошибка, то then не гарантирует очистку, но будет finally. В этом случае я отсутствовал.

+2

Также '.finally' не влияет на значение, разрешенное для обещания, тогда как'. Then' будет. – Matt

+0

@Matt, если функция возвращает 'undefined'. Но вы правы, 'finally()' гарантирует, что разрешенное значение не будет изменено. – Thomas

+0

@Thomas Извините, я не понимаю вашу 'неопределенную 'оговорку? Вы имеете в виду, что не видите эффект, если вы возвращаете 'undefined' всюду? – Matt

3

.then и .finally - это не то же самое.

.then является основным примитивным обещанием. Это то, что определено, полностью, в Promises/A+ spec, и все библиотеки обещаний реализуют его.

Обработчик Bluebird .finally будет «называться независимо от судьбы обещания». Таким образом, необработанное исключение все еще вызывает .finally.

new Promise((resolve, reject) => reject(false)) 
    .finally(a => console.log('finally', a)) 
// finally undefined 
// Unhandled rejection false 

new Promise((resolve, reject) => reject(false)) 
    .then(a => console.log('then', a)) 
// Unhandled rejection false 

.finally не изменит разрешенное значение обещания и не получить результат посыла цепи.

new Promise((resolve, reject) => reject(false)) 
    .catch(e => { 
    console.log(e) 
    return 2 
    }) 
    .finally(a => { 
    console.log('finally', a) 
    return 1 
    }) 
    .then(res => console.log('res', res)) 
// finally undefined 
// res 2 

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

+1

Кстати, если кто-то еще читает это, теперь, когда у меня есть эти понятия, я нашел несколько других вещей, а '.tap()' один: 'tap' вроде как на полпути между' then' и 'finally ': Подобно' then', он не вызван отказом, но, как 'finally', он не изменяет результат и поэтому предыдущий результат« пропускает »над ним. Ухоженная. –

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