简体   繁体   中英

How can I add optional callbacks to a typescript function?

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

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 :(" );
    } );

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 , eg

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).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM