3

jQuery 3 Deferred objects are supposed to be Promises/A+ compatible. From this question, it seems that the TypeScript compiler will yell at you for it. But this code compiles fine using the latest version of jQuery and TypeScript:

import $ from 'jquery';

(async () => {
    const response = await $.getJSON('https://api.github.com/');
    console.log(response);
})();

According to MDN:

If the value of the expression following the await operator is not a Promise, it's converted to a resolved Promise.

I don't see an issue here considering that the expression should already be returning a Promise.

  1. Does this mean it is safe to use await with $.ajax (and friends such as getJSON, post, etc.)? Or are there cases where the code will fail?
  2. Why is it OK to wrap Promise.resolve() around a jQuery 2 Deferred object that is not Promises/A+ compliant to make it a real Promise, but awaiting on a jQuery 2 Deferred object will fail?

I've referred to a TypeScript example above but I'm asking this question in the general context of JavaScript. If there are differences in how TypeScript compiler handles await versus how Node.js/Babel/browsers handles it in JavaScript, please elaborate in your answer.

rink.attendant.6
  • 44,500
  • 61
  • 101
  • 156
  • Can't speak to when TypeScript is targeting ES5. ES2015 (aka "ES6") `await` is perfectly happy with a jQuery 2 Deferred object and works correctly with it, even though jQuery 2 Deferreds aren't Promises/A+ compatible (because `await` effectively wraps *any* thenable in an actual promise, which deals with jQuery 2 Deferred's flaw of synchronous calls to `then` callbacks when already settled). – T.J. Crowder Feb 05 '18 at 08:37
  • @T.J.Crowder Is this a TypeScript thing? I might be mistaken but I thought the native JavaScript `await` wasn't compatible with jQuery 2 Deferred in certain cases... maybe if `done` and/or `fail` handlers were already attached to it? – rink.attendant.6 Feb 05 '18 at 08:57
  • As far as I know, native `await` is fine with jQuery 2 Deferreds. Example: https://jsfiddle.net/23s1nzmt/ Naturally, if you're also using features like `done` you get their idiosyncratic behavior. As I mentioned above, one of those is that calling `then` to hook up a handler on an already-settled Deferred will call handler *synchronously*, which is a no-no in Promises/A+. But because `await` uses a native promise instead, it irons out that issue. Example: https://jsfiddle.net/8kfyhs1m/1/ But again, that's all native. If TypeScript is targeting ES5 and polyfilling, I wouldn't know if it's safe. – T.J. Crowder Feb 05 '18 at 09:06
  • 2
    There might be issues with error handling. The problem is that jquery impl do not reject a promise if `onFulfill` handler throws. So you won't be able to catch this error using `try-catch` unless tsc does something really smart with the problem. Check this [example](https://jsfiddle.net/tarabyte/btf9ks51/) – Yury Tarabanko Feb 05 '18 at 09:29
  • @YuryTarabanko: Good point, another idiosyncratic behavior. If rink.attendant.6 sticks to converting to a native promise immediately (no `then` or `done` handlers on jQuery's on Deferred), he/she should be okay, but you start throwing those idiosyncratic behaviors in and it goes south fast. :-) – T.J. Crowder Feb 05 '18 at 10:02
  • @YuryTarabanko Feel free to add your response as an answer – rink.attendant.6 Feb 05 '18 at 15:16

0 Answers0