Question

I'm trying to filter an array of ajax Promise objects based on the jqXHR status. I can only get the status when it's 503 and when it's 200, status is undefined. How can I filter the array, only returning jqXHR objects with status 200

var userData = {};  
userData.user1 = {"creds":    {"userid":"user1@test.com","password":"user1pass","country":"us"}};
userData.user2 = {"creds":    {"userid":"user2@test.com","password":"user2pass","country":"mx"}};
userData.user3 = {"creds":    {"userid":"user3@test.com","password":"user3pass","country":"ca"}};
function loginUser(credentials){
    var requests = $.map(credentials, function(k, v){
        return $.ajax({
            url : '/path/to/my/uri', 
            type : 'post',
            contentType : 'application/json',
            data : JSON.stringify(v)
        });
    });
    console.log(requests);
    // return a promise that will resolve when all ajax calls are done
    return $.when.apply($, requests);
}

loginUser(userData).always(function() {
    // all logins completed here
    successes = $.grep(requests, function(v, i){
        console.log(v.status); // only outputs 503
        return v.status == 200; // undefined
    });
});
Was it helpful?

Solution

That's because the promises resolve with the actual value in a $.ajax call and not with the XHR itself.

If you only want the successes, you can resolve with the xhr itself instead of the result:

var requests = $.map(credentials, function(k, v){
    var xhr = $.ajax({
        url : '/path/to/my/uri', 
        type : 'post',
        contentType : 'application/json',
        data : JSON.stringify(v)
    });
    var xhr2 = xhr.then(function(result){ return xhr; }); //resolve with original
    return xhr2;
});

Alternatively, you can handle errors yourself and access only the successful deferred objects, stealing from my own answer from here:

//returns only fulfilled values from a list of promises
function some(promises){
    var d = $.Deferred(), results = [];
    var remaining = promises.length;
    for(var i = 0; i < promises.length; i++){
        promises[i].then(function(res){
            results.push(res); // on success, add to results
        }).always(function(res){
            remaining--; // always mark as finished
            if(!remaining) d.resolve(results);
        })
    }
    return d.promise(); // return a promise on the remaining values
}

And do:

function loginUser(credentials){
   ...
   return some(requests);
}

loginUser(userData).then(function(results){
    //results is only the results of successful requests here.
});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top