jQuery deferreds and promises - .then() vs .done()

后端 未结 10 1347
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-11-22 06:16

I\'ve been reading about jQuery deferreds and promises and I can\'t see the difference between using .then() & .done() for successful callbacks

10条回答
  •  长发绾君心
    2020-11-22 06:57

    Only use .then()

    These are the disadvantages of .done()

    • can not be chained
    • block resolve() call (all .done() handlers will be executed synchronous)
    • resolve() might get an exception from registered .done() handlers(!)
    • an exception in a .done() half-kills the deferred:
      • further .done() handlers will be silently skipped

    I thought temporarily that .then(oneArgOnly) always requires .catch() so that no exception gets silently ignored, but that is not true any more: the unhandledrejection event logs unhandled .then() exceptions on the console (as default). Very reasonable! No reason left to use .done() at all.

    Proof

    The following code snippet reveals, that:

    • all .done() handlers will be called synchronous at point of resolve()
      • logged as 1, 3, 5, 7
      • logged before the script falls through bottom
    • exception in a .done() influences resolve() caller
      • logged via catch around resolve()
    • exception breaks promise from further .done() resolution
      • 8 and 10 are not logged!
    • .then() has none of these problems
      • logged as 2, 4, 6, 9, 11 after thread turns idle
      • (snippet environment has no unhandledrejection is seems)

    Btw, exceptions from .done() can’t be properly caught: because of the synchronous pattern of .done(), the error is either thrown at the point of .resolve() (might be library code!) or at the .done() call which attaches the culprit if the deferred is already resolved.

    console.log('Start of script.');
    let deferred = $.Deferred();
    // deferred.resolve('Redemption.');
    deferred.fail(() => console.log('fail()'));
    deferred.catch(()=> console.log('catch()'));
    deferred.done(() => console.log('1-done()'));
    deferred.then(() => console.log('2-then()'));
    deferred.done(() => console.log('3-done()'));
    deferred.then(() =>{console.log('4-then()-throw');
        throw 'thrown from 4-then()';});
    deferred.done(() => console.log('5-done()'));
    deferred.then(() => console.log('6-then()'));
    deferred.done(() =>{console.log('7-done()-throw');
        throw 'thrown from 7-done()';});
    deferred.done(() => console.log('8-done()'));
    deferred.then(() => console.log('9-then()'));
    
    console.log('Resolving.');
    try {
        deferred.resolve('Solution.');
    } catch(e) {
        console.log(`Caught exception from handler
            in resolve():`, e);
    }
    deferred.done(() => console.log('10-done()'));
    deferred.then(() => console.log('11-then()'));
    console.log('End of script.');

提交回复
热议问题