Read more

JavaScript: Polyfill native Promise API with jQuery Deferreds

Henning Koch
August 05, 2017Software engineer at makandra GmbH

Native Promise is supported by all current browsers.

You should prefer native promises Show archive.org snapshot to jQuery's Deferreds Show archive.org snapshot . Native promises are much faster than their jQuery equivalent.

Illustration UI/UX Design

UI/UX Design by makandra brand

We make sure that your target audience has the best possible experience with your digital product. You get:

  • Design tailored to your audience
  • Proven processes customized to your needs
  • An expert team of experienced designers
Read more Show archive.org snapshot

Native promises are supported on all browsers except IE <=11, Android <= 4.4 and iOS <= 7 Show archive.org snapshot .

If you need Promise support for these old browsers you can use a Polyfill. A very fast and small (2 KB minified and gzipped) polyfill is Zousan Show archive.org snapshot .

If you want to waste even fewer bytes, you can use jQuery's deferreds to polyfill the native Promise API. The result is extremely small (339 bytes minfied and gzipped), but has the same performance limitations of jQuery deferreds. Obviously this makes only sense in a project that is using jQuery anyway.

Below is the polyfill in Coffeescript Show archive.org snapshot . It is mostly compliant with Promises A+ spec if you are using jQuery 3+:

window['Promise'] ||= class

  constructor: (executor) ->
    @deferred = $.Deferred()
    executor(@deferred.resolve, @deferred.reject)

  then: (fulfilled, rejected) =>
    @deferred.then(fulfilled, rejected)

  catch: (rejected) =>
    @then(undefined, rejected)

  @race: (promises) ->
    settled = false
    winner = $.Deferred()

    settle = (settler, value) ->
      unless settled
        settled = true
        winner[settler](value)
      undefined

    fulfilled = settle.apply(this, 'resolve')
    rejected = settle.apply(this, 'reject')

    for promise in promises
      promise.then(fulfilled, rejected)

    winner.promise()

  @all: (promises) ->
    # Pass an additional resolved deferred to $.when so $.when will
    # not return the given deferred if only one deferred is passed.
    $.when(@resolve(), promises...)

  @reject: (value) ->
    deferred = $.Deferred()
    deferred.reject(value)
    deferred.promise()

  @resolve: (value) ->
    deferred = $.Deferred()
    deferred.resolve(value)
    deferred.promise()
Posted by Henning Koch to makandra dev (2017-08-05 16:33)