HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Wrapping jQuery empty() To Include A Callback

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
includeemptycallbackjquerywrapping

Problem

I needed to write a method to extend the jQuery empty() function to include a callback. Since I didn't want to mess with namespaces, closures, etc, I instead wrote a regular function to wrap empty().

var emptyWithCallback = function(node, callback) {
    console.log('Entered emptyWithCallback()');
    if (typeof callback != 'function') {
        return false;
    }
    var doTheCallback = callbackWrapper();
    var doTheEmpty = myEmpty();

    function callbackWrapper() {
        var deferredCallback = $.Deferred();
        callback();
        deferredCallback.resolve();

        return deferredCallback.promise();
    }

    function myEmpty() {
        var deferredEmpty = $.Deferred();
        $(node).empty();
        deferredEmpty.resolve();

        return deferredEmpty.promise();
    }

    doTheCallback.then(doTheEmpty);
}


I was attempting to use the $.Deferred() in case the callback contained an ajax call, in order to not execute the .empty() until the callback concluded.

Does this code look like it will work? It seems to work on simple callbacks, such as a single alert() or console.log().

Solution

I can't really see how wrapping empty() with a $.Deferred object manages to achieve anything; after all empty() executes immediately and doesn't need the consumer to wait for a function callback.

Instead think of how you might be using empty() with an asynchronous context and then abstract that. For example if it is an AJAX request which you need to empty an element out, then fetch, then display the new data your implementation might look like this:

var clearAndThenFetch = function($element, ajaxOptions, callback) {
    var deferred = $.Deferred();

    $element.empty();

    $.ajax($.extend({
        success: function(response) {
            callback && callback(deferred, response) || deferred.resolve();
        },
        error: function(xhr) {
            deferred.reject(JSON.parse(xhr.responseText).errors);
        }
    }, ajaxOptions));

    return deferred.promise();
};


Otherwise I can't really see the need for abstraction here.

Edit: In regards to Flambino's comment, why do you need the empty() deferred at all? Remember that DOM operations are synchronous and so don't need to use promises. With this in mind we can rewrite your function like so:

var emptyWithCallback = function(node, callback) {
    console.log('Entered emptyWithCallback()');
    if (typeof callback != 'function') {
        return false;
    }

    var doTheCallback = function() {
        var deferredCallback = $.Deferred();
        callback();
        deferredCallback.resolve();

        return deferredCallback.promise();
    }

    doTheCallback.then(function() {
        $(node).empty();
    });
}

Code Snippets

var clearAndThenFetch = function($element, ajaxOptions, callback) {
    var deferred = $.Deferred();

    $element.empty();

    $.ajax($.extend({
        success: function(response) {
            callback && callback(deferred, response) || deferred.resolve();
        },
        error: function(xhr) {
            deferred.reject(JSON.parse(xhr.responseText).errors);
        }
    }, ajaxOptions));

    return deferred.promise();
};
var emptyWithCallback = function(node, callback) {
    console.log('Entered emptyWithCallback()');
    if (typeof callback != 'function') {
        return false;
    }

    var doTheCallback = function() {
        var deferredCallback = $.Deferred();
        callback();
        deferredCallback.resolve();

        return deferredCallback.promise();
    }

    doTheCallback.then(function() {
        $(node).empty();
    });
}

Context

StackExchange Code Review Q#68022, answer score: 5

Revisions (0)

No revisions yet.