2

I can make a javascript ajax call as follows:

$.getJSON( "http://localhost:62178/document?filename=c:/test/dave.docx", function( data ) {
    console.log("read = " + data);
}).done(function(e) {
    console.log( "second success" );
})
    .fail(function(e, f, g) {
        console.log( "error" );
    })
    .always(function(e) {
        console.log( "complete" );
    });

How can I declare and write a typescript class that does the equivalent? In other words, if my class has a getJSON() method, how do I write it so I have the main function and the optional named functions?

thanks - dave

2 Answers 2

2

After being asked for an example in the comments, I decided to post this as a separate answer to make it easier to distinguish between them.

Of course there is a lot to improve. For example one thing that could be done is to allow attaching handlers to the promise even after the deferred has been resolved (they will just fire immediately). That way the could can also handle synchronous requests.

And of course you can add other callbacks etc. Again, just a small example! :)

enum Status {
    SUCCESSFUL, FAILED
}

interface Callback { (): void; }

class Deferred {
    public promise : Promise = new Promise();

    public resolve( status : Status = Status.SUCCESSFUL ) {
        if( status === Status.SUCCESSFUL ) {
            this.executeCallback( this.promise.cbSuccess );
        } else {
            this.executeCallback( this.promise.cbFail );
        }
    }

    private executeCallback( callback : Callback ) {
        if( callback ) {
            callback.call( null );
        }
    }
}

class Promise {
    public cbSuccess : Callback;
    public cbFail : Callback;

    public success( callback : Callback ) : Promise {
        this.cbSuccess = callback;
        return this;
    }

    public fail( callback : Callback ) : Promise {
        this.cbFail = callback;
        return this;
    }
}

// =======
// Example
// =======

function getJson( url : string ) : Promise {
    var deferred = new Deferred();

    // simulate some asynchronous operation
    setTimeout( function someAsynchRequest() {
        var result = Math.random() < 0.5
            ? Status.SUCCESSFUL : Status.FAILED;

        console.log( "Asynchronous operation finished [result: "
            + Status[result] + "]!" );

        // resolve our deferred with the result we got
        deferred.resolve( result );
    }, 3000 );

    // return only the promise because the caller actually
    // doesn't need to know about the deferred itself
    // (e.g. the caller shouldn't be able to resolve it)
    return deferred.promise;
}

getJson( "no one cares" )
    .success( function () {
        console.log( "Callback came back with success!" );
    } ).fail( function () {
        console.log( "Callback came back with failure :(" );
    } );
Sign up to request clarification or add additional context in comments.

Comments

1

tl;dr Learn about promises and deferreds

A good way to learn about this from the Typescript perspective might be looking at DefinitelyTyped to see how they're typing jQuery.

The definition(s) for getJSON can be found here, e.g.

getJSON(url: string, success?: (data: any, textStatus: string, jqXHR: JQueryXHR) => any): JQueryXHR;

As you can see, it returns a new type JQueryXHR which is an interface that can be found here:

interface JQueryXHR extends XMLHttpRequest, JQueryPromise<any> {
    overrideMimeType(mimeType: string): any;
    abort(statusText?: string): void;
}

This, in turn, references JQueryPromise, which can be found here and now contains all these callbacks:

interface JQueryPromise<T> {
    always(alwaysCallbacks1?: JQueryPromiseCallback<T>, ...alwaysCallbacks2: JQueryPromiseCallback<T>[]): JQueryDeferred<T>;
    done(doneCallbacks1?: JQueryPromiseCallback<T>, ...doneCallbacks2: JQueryPromiseCallback<T>[]): JQueryDeferred<T>;
    fail(failCallbacks1?: JQueryPromiseCallback<T>, ...failCallbacks2: JQueryPromiseCallback<T>[]): JQueryDeferred<T>;
    // … and so on …
}  

That would be the Typescript part. If you're interested in the actual implementation, you could have a look at the jQuery source directly. The basic idea is that the method only returns a promise to which you can add your handlers. The deferred will then resolve and call the attached handlers.

A rather quick example would be the following; (I have removed the example because an example that misses the point is not really worth anything and might, if anything, give wrong ideas).

2 Comments

I'm struggling (ie failing) on how to implement the guts of this. Somehow I need to take the getJSON call I am using in my typescript function and when it calls back, then callback the always/done/fail I have defined in the interface my function returns. Any example of that part? TIA
@DavidThielen I have added another answer with a small example. I hope it helps!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.