I'm playing around with returning promises from an AJAX method and seeing how I can use them to make my code more easier to read/functional. My current scenario is to have a function getBookIds
which issues an AJAX call to a database to return the title of a book based on its ID. There are five books in the table and an anchor tag whose text property corresponds to each book. I want some other fancy AJAX method to fire once all anchor tags have been clicked on. Here's what I've got so far:
HTML
<a href="#">1</a>
<a href="#">3</a>
<a href="#">4</a>
<a href="#">5</a>
<a href="#">7</a>
JS
//hacky globals
var bookArray = [];
bookArray.length = $('a').length;
//ajax function
function getBookIds(data) {
return $.ajax({
type: "POST",
url: "Service.asmx/GetBookById",
data: JSON.stringify({
'titleId': data
}),
dataType: "json",
contentType: "application/json"
});
}
//click handler
$('a').on('click', function () {
var index = $('a').index($(this));
var titleId = $(this).text();
getBookIds(titleId).done(function (results) {
bookArray[index] = results.d;
var isEmpty = arrayChecker(bookArray);
fancyAjax(isEmpty);
});
});
//checks for undefined values in the array
function arrayChecker(array) {
var isEmpty = 0;
$.each(array, function (key, val) {
if (val === undefined) {
isEmpty++;
}
});
return (isEmpty > 0);
}
//bool comes from arrayChecker if no undefined then go AJAX
function fancyAjax(bool) {
if (!bool) {
alert('alert message for fancy stuff');
}
}
This is a contrived example, but I'm struggling to see how I could incorporate these promises into my daily work. Is this just a bad example to leverage the power of promises/deferreds in the first place? It seems that instead of the success
callback on AJAX, not I've got all my logic rolled up inside done
. Any suggestions on tackling this better?
Returns a new Promise object that is resolved with the given value. If the value is a thenable (i.e. has a then method), the returned promise will "follow" that thenable, adopting its eventual state; otherwise, the returned promise will be fulfilled with the value.
There is no need to use a return statement inside a new Promise() callback. The Promise constructor is not expecting any sort of return value from the callback. So, the reason to use a return statement inside that callback is only to control the flow of execution in that function.
Inside an async function, you can use the await keyword before a call to a function that returns a promise. This makes the code wait at that point until the promise is settled, at which point the fulfilled value of the promise is treated as a return value, or the rejected value is thrown.
Promise callbacks are handled as a Microtask whereas setTimeout() callbacks are handled as Task queues.
I want some other fancy AJAX method to fire once all anchor tags have been clicked on.
That sounds like you want to get a promise for each click, which you can then combine into a promise for all clicks. The point is not to use a global booksArray
, but an array of promises.
function getBookIds(data) { … } //ajax function as before
var promises = $('a').map(function() {
var $this = $(this),
click = $.Deferred();
$this.one('click', function() { // click handler
click.resolve($this.text());
});
return click.then(getBookIds); // returns a promise for the ajax result
// after the link has been clicked
}).toArray();
$.when.apply($, promises).then(function fancyAjax() {
alert('alert message for fancy stuff');
});
(Demo)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With