Yuri Yuri -4 years ago 106
jQuery Question

Return value from class function

I'm trying to build a class of custom alerts, based on Boostrap. Everything is still very young but I encountered a problem. How can I return a value according to the clicked button only when the click event happens? Here you can see how I set the value (very easy, for tests)

$modal.on('click', '[data-alertify="cancel"]', function(){
var value = 'no';
$modal.modal('hide');
return value;
});
$modal.on('click', '[data-alertify="confirm"]', function(){
var value = 'yes';
$modal.modal('hide');
return value;
});


Here is my class and test code JSFiddle

As you can see, the alert (obviously) appears before the modal is shown. How should I handle this? How can I wait for the correct value to be returned, and then alert it?

Answer Source

The issue is that these callback functions are called asynchronously, and the value returned by the return statements therein are not available to you afterwards. The following construct would only work if the whole process were synchronous:

var ret = Alertify.alert({
   content: 'This is MY alert content!'
});

... but Alertify.alert() does not return the desired value, since the user has not yet clicked. This alert() function does not return anything, and could certainly not return the result of a click that still has to happen.

This scenario is ideal for introducing promises. This is how it looks when you do that:

First change the showModal function to return a promise:

var showModal = function (alert_id) {
  $('body').append($html);
  var $modal = $('#' + alert_id);
  $modal.modal('show');
  var dfd = $.Deferred(); // create a promise
  $modal.on('click', '[data-alertify="cancel"]', function(){
    var value = 'no';
    $modal.modal('hide');
    dfd.resolve(value); // instead of returning the value, resolve the promise with it
  });
  $modal.on('click', '[data-alertify="confirm"]', function(){
    var value = 'yes';
    $modal.modal('hide');
    dfd.resolve(value);
  });
  $modal.on('hidden.bs.modal', function(){
    $(this).remove();
    dfd.resolve();
  });
  return dfd.promise(); // return the (unresolved) promise
};

Now Alertify.alert will return a promise object, which exposes a then method, to which you pass a callback:

Alertify.alert({
  content: 'This is MY alert content!'
}).then(function(ret) {
   alert(ret);
});

... and that's it.

Here is the updated fiddle.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download