Migrating from jQuery to ES6 promises

If you’re reading this blog, chances are that at some point you’ve used jQuery to build/partially build a website. jQuery definitely has its uses (more so in the past than now), but some of its constructs, like its promises/deferred objects, conflict with today’s promise standards. As such, as part of a big refactor, I migrated one of the projects I maintain from using jQuery promises/deferred objects to ES6 promises/event handlers.

Migrating callbacks/then()’s/fail()’s

Both ES6 and JQuery promises support the .then() and .fail() promise chains. That said, if you’re going about cleaning up promise code, you ought to upgrade these chains to the far neater/more concise async/await constuct.

Example 1 — Cleaning up a simple .then() and .fail()

// Before
function bar() {
foo()
.then(function() {
console.log(‘Success’);
})
.fail(function() {
console.log(‘Error’);
});
}
// After
async function bar() {
try {
await foo();
console.log(‘Success’);
} catch {
console.log(‘Error’);
}
}

Example 2 — Cleaning up .then() and .fail() callbacks

// Before
function bar() {
executeFoo(function() {
console.log(‘Success’);
},
function() {
console.log(‘Error’);
});
}
function executeFoo(successCallback, errorCallback) {
foo()
.then(successCallback)
.fail(errorCallback);
}
// After
async function bar() {
try {
await foo();
console.log(‘Success’);
} catch {
console.log(‘Error’);
}
}

Migrating $.Deferred() notifications

JQuery’s $.Deferred() objects provided an easy way to create progress handlers. Whilst easy, progress notifcations aren’t supported by ES6 promises; the newer definitions of promises have only two states — successfully completed or failed. Given this, in order to migrate from $.Deferred() objects, you need to use a combination of promises and event listeners.

// Before
function notifyEvery500MS (progressCallback) {
const deferred = $.Deferred();
let count = 0;
 const interval = setInterval(function () {
if (count === 10) {
clearInterval(interval);
deferred.resolve();
}
else {
count += 1;
deferred.notify(progressCallback);
}
}, 500);
return deferred;
}
// After (a bit more involved)
function notifyEvery500MS (progressCallback) {
let count = 0;
 const interval = setInterval(function() {
window.dispatchEvent(new CustomEvent(‘notify’, {detail: count}));
count += 1;
}, 500);
return Promise.resolve({then: function(onfulfilled) {
window.addEventListener(‘notify’, function notifyListener(e) {
if (e.detail === 10) {
clearInterval(interval);
window.removeEventListener(‘notify’, notifyListener);
onfulfilled();
}
else {
progressCallback();
}
});
}});
}

Whilst often daunting (and seemingly pointless to numerous project managers), refactoring a codebase to bring it in line with today’s standards is vital to the survival of the project. Don’t put refactors off and let your codebase ferment as much as the one I inherited did!

Find more about Tom Szpytman at tomszpytman.com

Like what you read? Give Tom Szpytman a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.