Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning Promises for use in click handlers

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?

like image 608
wootscootinboogie Avatar asked Jan 13 '14 21:01

wootscootinboogie


People also ask

How do you handle return promises?

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.

Do promises have to return?

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.

How do you use promises to handle Asynchronicity?

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.

Which are callbacks used for handling promises?

Promise callbacks are handled as a Microtask whereas setTimeout() callbacks are handled as Task queues.


1 Answers

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)

like image 173
Bergi Avatar answered Oct 05 '22 04:10

Bergi