Skip to content

Commit

Permalink
refactor(ajax): move helper methods
Browse files Browse the repository at this point in the history
- moves get, post, and getJSON to live on Observable.ajax (e.g. Observable.ajax.get)
- changes signatures of helper methods to be more refined for common use cases
- adds post and delete helpers

BREAKING CHANGE: get, post and getJSON helpers no longer live directly on Observable, they have been moved to Observable.ajx (e.g. Observable.ajax.get, Observable.ajax.post, etc)
BREAKING CHANGE: helpers for get and post no longer take Request (options) objects as parameters. If that feature is required, use the ajax method directly.
  • Loading branch information
benlesh committed Jan 13, 2016
1 parent 6df755f commit fbe726d
Show file tree
Hide file tree
Showing 11 changed files with 115 additions and 63 deletions.
62 changes: 62 additions & 0 deletions spec/observables/dom/ajax-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -240,4 +240,66 @@ describe('Observable.ajax', function () {
'responseText': expected
});
});

describe('ajax.get', function () {
it('should succeed on 200', function () {
var expected = 'some response';
var result;
var complete = false;

Rx.Observable
.ajax.get('/flibbertyJibbet')
.subscribe(function(x) {
result = x;
}, function () {
throw 'should not have been called';
}, function () {
complete = true;
});

expect(jasmine.Ajax.requests.mostRecent().url).toBe('/flibbertyJibbet');

jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
'contentType': 'application/json',
'responseText': expected
});

expect(result).toBe(expected);
expect(complete).toBe(true);
});


it('should succeed on 200 with a resultSelector', function () {
var expected = 'hahahahaha';
var result, innerResult;
var complete = false;

Rx.Observable
.ajax.get('/flibbertyJibbet', function (x) {
innerResult = x;
return x.response.toUpperCase();
})
.subscribe(function(x) {
result = x;
}, function () {
throw 'should not have been called';
}, function () {
complete = true;
});

expect(jasmine.Ajax.requests.mostRecent().url).toBe('/flibbertyJibbet');

jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
'contentType': 'application/json',
'responseText': expected
});

expect(innerResult.xhr).toBeDefined();
expect(innerResult.response).toBe(expected);
expect(result).toBe('HAHAHAHAHA');
expect(complete).toBe(true);
});
});
});
7 changes: 2 additions & 5 deletions src/Observable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {race as raceStatic} from './operator/race-static';
import {RangeObservable} from './observable/range';
import {InfiniteObservable} from './observable/never';
import {ErrorObservable} from './observable/throw';
import {AjaxCreationMethod} from './observable/dom/ajax';

/**
* A representation of any set of values over any amount of time. This the most basic building block
Expand Down Expand Up @@ -160,12 +161,8 @@ export class Observable<T> implements CoreOperators<T> {
return this.source.subscribe(subscriber);
}

static get: <T>(url: string | any) => Observable<any>;
static post: <T>(url: string | any, body?: any) => Observable<any>;
static ajax: <T>(options: string | any) => Observable<any>;
static getJSON: <T>(url: string | any) => Observable<any>;

// static method stubs
static ajax: AjaxCreationMethod;
static bindCallback: typeof BoundCallbackObservable.create;
static combineLatest: typeof combineLatestStatic;
static concat: typeof concatStatic;
Expand Down
3 changes: 0 additions & 3 deletions src/Rx.DOM.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,7 @@ import './add/observable/throw';
import './add/observable/timer';
import './add/operator/zip-static';

import './add/observable/dom/get';
import './add/observable/dom/post';
import './add/observable/dom/ajax';
import './add/observable/dom/getJSON';

//operators
import './add/operator/buffer';
Expand Down
2 changes: 1 addition & 1 deletion src/add/observable/dom/ajax.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {Observable} from '../../../Observable';
import { AjaxObservable } from '../../../observable/dom/ajax';
import { AjaxObservable, AjaxCreationMethod } from '../../../observable/dom/ajax';
Observable.ajax = AjaxObservable.create;

export var _void: void;
5 changes: 0 additions & 5 deletions src/add/observable/dom/get.ts

This file was deleted.

5 changes: 0 additions & 5 deletions src/add/observable/dom/getJSON.ts

This file was deleted.

5 changes: 0 additions & 5 deletions src/add/observable/dom/post.ts

This file was deleted.

52 changes: 50 additions & 2 deletions src/observable/dom/ajax.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,39 @@ const createXHRDefault = (): XMLHttpRequest => {
}
};

export interface AjaxCreationMethod {
(): <T>(urlOrRequest: string | AjaxRequest) => Observable<T>;
get: <T>(url: string, resultSelector?: (response: AjaxResponse) => T, headers?: Object) => Observable<T>;
post: <T>(url: string, body?: any, headers?: Object) => Observable<T>;
put: <T>(url: string, body?: any, headers?: Object) => Observable<T>;
delete: <T>(url: string, headers?: Object) => Observable<T>;
getJSON: <T, R>(url: string, resultSelector?: (data: T) => R, headers?: Object) => Observable<R>;
}

function defaultGetResultSelector<T>(response: AjaxResponse): T {
return response.response;
}

export function ajaxGet<T>(url: string, resultSelector: (response: AjaxResponse) => T = defaultGetResultSelector, headers: Object = null) {
return new AjaxObservable<T>({ method: 'GET', url, resultSelector, headers });
};

export function ajaxPost<T>(url: string, body?: any, headers?: Object): Observable<T> {
return new AjaxObservable<T>({ method: 'POST', url, body, headers });
};

export function ajaxDelete<T>(url: string, headers?: Object): Observable<T> {
return new AjaxObservable<T>({ method: 'DELETE', url, headers });
};

export function ajaxPut<T>(url: string, body?: any, headers?: Object): Observable<T> {
return new AjaxObservable<T>({ method: 'PUT', url, body, headers });
};

export function ajaxGetJSON<T, R>(url: string, resultSelector?: (data: T) => R, headers?: Object): Observable<R> {
const finalResultSelector = resultSelector ? (res: AjaxResponse) => resultSelector(res.response) : null;
return new AjaxObservable<R>({ method: 'GET', url, responseType: 'json', resultSelector: finalResultSelector, headers });
};
/**
* Creates an observable for an Ajax request with either a request object with url, headers, etc or a string for a URL.
*
Expand All @@ -60,13 +93,27 @@ const createXHRDefault = (): XMLHttpRequest => {
* @returns {Observable} An observable sequence containing the XMLHttpRequest.
*/
export class AjaxObservable<T> extends Observable<T> {
static create<T>(options: string | any): Observable<T> {
static create: AjaxCreationMethod = (() => {
const create: any = (urlOrRequest: string | AjaxRequest) => {
return new AjaxObservable(urlOrRequest);
};

create.get = ajaxGet;
create.post = ajaxPost;
create.delete = ajaxDelete;
create.put = ajaxPut;
create.getJSON = ajaxGetJSON;

return <AjaxCreationMethod>create;
})();

static create2<T>(options: string | AjaxRequest): Observable<T> {
return new AjaxObservable(options);
}

private request: AjaxRequest;

constructor(options: string | any) {
constructor(options: string | AjaxRequest) {
super();

const request: AjaxRequest = {
Expand All @@ -88,6 +135,7 @@ export class AjaxObservable<T> extends Observable<T> {
}
}
}
request.headers = request.headers || {};

if (!request.crossDomain && !request.headers['X-Requested-With']) {
request.headers['X-Requested-With'] = 'XMLHttpRequest';
Expand Down
12 changes: 0 additions & 12 deletions src/observable/dom/get.ts

This file was deleted.

12 changes: 0 additions & 12 deletions src/observable/dom/getJSON.ts

This file was deleted.

13 changes: 0 additions & 13 deletions src/observable/dom/post.ts

This file was deleted.

0 comments on commit fbe726d

Please sign in to comment.