2

I am looking for the best way to fix this situation. I need additional checks of the returned Ajax data that could cause my _loadPanel promise operation to "fail":

_loadPanel(url: string, data?: any) : JQueryPromise<any>
{
    return $.ajax(
        {
            url: url,
            type: data ? "POST" : "GET",
            data: data
        }).done(function (html: string, textStatus: string)
        {
             // Some function that exracts required data
             var $panel = extractPanelData(html);
             if (!$panel.length)
             {
                 // How to cause a reject here???
             }
        });
}

You can't do this (below) as the promise returned from Ajax is immutable and it just smells wrong anyway:

var promise = $.ajax({...}).done(function(...)
{ 
     promise.reject("Data failed promise");
});

Is there a simple way of doing this that does not involve adding an extra $.Deferred() object or is that the only pattern?

Attempts:

I have tried the following, so that I could modify a parent Deferred object but it will not compile:

var dfd = $.Deferred();
var promise = dfd.promise();
promise = promise.then($.ajax(
            {
                cache: false,
                url: url,
                type: data ? "POST" : "GET",
                data: data
            }).done(...));

It will to allow me to combine an Ajax promise with a Deferred promise

Supplied parameters do not match any signature of call target:Type '(value: {}) => {}' requires a call signature, but type 'JQueryXHR' lacks one.

Suggestions?

Something cool:

Not sure how widely known this is, and it does not help this problem (as it also returned an immutable promise), but it appears you can use $.when to pass initial parameters to the first function

e.g. passing initial parameters to $.ajax like this:

    $.when({
            url: url,
            type: data? "POST" : "GET",
            data: data
        }).then($.ajax).done(function (html: string, textStatus: string)

or separate parameters like this:

$.when("Hello!", 22, "There!")
    .then(insertPanel);

This can have interesting benefits if the result is chained to previous promises as the Ajax call is not longer run immediately, but only after the previous steps complete.

iCollect.it Ltd
  • 92,391
  • 25
  • 181
  • 202

1 Answers1

0

There are a few thigns here:

  • .then chains promises and changes their state.
  • .done does not chain promises, but adds a handler to the current promise and returns it.

So:

var xhr = $.ajax({...});
p = xhr.then(function(data){
    // fail if check fails
    if(additionalChecksFail) return $.Deferred.reject(Error("Invalid Request").promise(); 
    return data; // otherwise we maintain the same data
});

p.then(function(data){
   // will only run if data validation passed.
});
Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504
  • I though `done` returned the original promise as they do indeed chain (usually to `fail` next). – iCollect.it Ltd Jun 20 '14 at 18:53
  • @TrueBlueAussie yes, it returns the original promise, it does not chain promises (think of an actual chain for this analogy :)). – Benjamin Gruenbaum Jun 20 '14 at 19:53
  • I am confused then why I couldn't do `.then($ajax().done())` which is what my attempt was doing (if you ignore the detail). That should be the same object as `.then($ajax())` which I thought was valid. Is this just a strong typing issue with Typescript? – iCollect.it Ltd Jun 20 '14 at 19:56
  • @TrueBlueAussie `$ajax` returns a promise where `.then` accepts a function you can do `.then(function(res){ return $.ajax(..); })` this is like how you pass a callback function instead of invoke it directly. – Benjamin Gruenbaum Jun 20 '14 at 19:58
  • I have been using `then` to chain functions that return promises in tests. http://jsfiddle.net/TrueBlueAussie/s8XmJ/1/ It runs the promises sequentially, chains the results for subsequent `then`s – iCollect.it Ltd Jun 20 '14 at 20:02
  • Benjamin, those two bullet points could be better phrased. As they stand, they are very misleading. – Roamer-1888 Jun 22 '14 at 03:56
  • Just back from holiday. Will be trying it tomorrow. Thanks for your patience. :) – iCollect.it Ltd Aug 03 '14 at 22:16