From fbe726d3e2c2fd2906cac7ae40f81a2d4e363e0d Mon Sep 17 00:00:00 2001 From: Ben Lesh Date: Wed, 6 Jan 2016 13:43:10 -0800 Subject: [PATCH] refactor(ajax): move helper methods - 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. --- spec/observables/dom/ajax-spec.js | 62 +++++++++++++++++++++++++++++++ src/Observable.ts | 7 +--- src/Rx.DOM.ts | 3 -- src/add/observable/dom/ajax.ts | 2 +- src/add/observable/dom/get.ts | 5 --- src/add/observable/dom/getJSON.ts | 5 --- src/add/observable/dom/post.ts | 5 --- src/observable/dom/ajax.ts | 52 +++++++++++++++++++++++++- src/observable/dom/get.ts | 12 ------ src/observable/dom/getJSON.ts | 12 ------ src/observable/dom/post.ts | 13 ------- 11 files changed, 115 insertions(+), 63 deletions(-) delete mode 100644 src/add/observable/dom/get.ts delete mode 100644 src/add/observable/dom/getJSON.ts delete mode 100644 src/add/observable/dom/post.ts delete mode 100644 src/observable/dom/get.ts delete mode 100644 src/observable/dom/getJSON.ts delete mode 100644 src/observable/dom/post.ts diff --git a/spec/observables/dom/ajax-spec.js b/spec/observables/dom/ajax-spec.js index 682605fa5c..c84d05e3d3 100644 --- a/spec/observables/dom/ajax-spec.js +++ b/spec/observables/dom/ajax-spec.js @@ -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); + }); + }); }); diff --git a/src/Observable.ts b/src/Observable.ts index ba3ce4ee20..2b6ffc5b59 100644 --- a/src/Observable.ts +++ b/src/Observable.ts @@ -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 @@ -160,12 +161,8 @@ export class Observable implements CoreOperators { return this.source.subscribe(subscriber); } - static get: (url: string | any) => Observable; - static post: (url: string | any, body?: any) => Observable; - static ajax: (options: string | any) => Observable; - static getJSON: (url: string | any) => Observable; - // static method stubs + static ajax: AjaxCreationMethod; static bindCallback: typeof BoundCallbackObservable.create; static combineLatest: typeof combineLatestStatic; static concat: typeof concatStatic; diff --git a/src/Rx.DOM.ts b/src/Rx.DOM.ts index 15fd64953a..a06c969b53 100644 --- a/src/Rx.DOM.ts +++ b/src/Rx.DOM.ts @@ -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'; diff --git a/src/add/observable/dom/ajax.ts b/src/add/observable/dom/ajax.ts index ba6bc0d6de..4aed371739 100644 --- a/src/add/observable/dom/ajax.ts +++ b/src/add/observable/dom/ajax.ts @@ -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; diff --git a/src/add/observable/dom/get.ts b/src/add/observable/dom/get.ts deleted file mode 100644 index f3b808358a..0000000000 --- a/src/add/observable/dom/get.ts +++ /dev/null @@ -1,5 +0,0 @@ -import {Observable} from '../../../Observable'; -import {get} from '../../../observable/dom/get'; -Observable.get = get; - -export var _void: void; diff --git a/src/add/observable/dom/getJSON.ts b/src/add/observable/dom/getJSON.ts deleted file mode 100644 index 7ba03ee739..0000000000 --- a/src/add/observable/dom/getJSON.ts +++ /dev/null @@ -1,5 +0,0 @@ -import {Observable} from '../../../Observable'; -import {getJSON} from '../../../observable/dom/getJSON'; -Observable.getJSON = getJSON; - -export var _void: void; diff --git a/src/add/observable/dom/post.ts b/src/add/observable/dom/post.ts deleted file mode 100644 index 53265a4053..0000000000 --- a/src/add/observable/dom/post.ts +++ /dev/null @@ -1,5 +0,0 @@ -import {Observable} from '../../../Observable'; -import {post} from '../../../observable/dom/post'; -Observable.post = post; - -export var _void: void; diff --git a/src/observable/dom/ajax.ts b/src/observable/dom/ajax.ts index 7a604ae32a..d93ea4b159 100644 --- a/src/observable/dom/ajax.ts +++ b/src/observable/dom/ajax.ts @@ -38,6 +38,39 @@ const createXHRDefault = (): XMLHttpRequest => { } }; +export interface AjaxCreationMethod { + (): (urlOrRequest: string | AjaxRequest) => Observable; + get: (url: string, resultSelector?: (response: AjaxResponse) => T, headers?: Object) => Observable; + post: (url: string, body?: any, headers?: Object) => Observable; + put: (url: string, body?: any, headers?: Object) => Observable; + delete: (url: string, headers?: Object) => Observable; + getJSON: (url: string, resultSelector?: (data: T) => R, headers?: Object) => Observable; +} + +function defaultGetResultSelector(response: AjaxResponse): T { + return response.response; +} + +export function ajaxGet(url: string, resultSelector: (response: AjaxResponse) => T = defaultGetResultSelector, headers: Object = null) { + return new AjaxObservable({ method: 'GET', url, resultSelector, headers }); +}; + +export function ajaxPost(url: string, body?: any, headers?: Object): Observable { + return new AjaxObservable({ method: 'POST', url, body, headers }); +}; + +export function ajaxDelete(url: string, headers?: Object): Observable { + return new AjaxObservable({ method: 'DELETE', url, headers }); +}; + +export function ajaxPut(url: string, body?: any, headers?: Object): Observable { + return new AjaxObservable({ method: 'PUT', url, body, headers }); +}; + +export function ajaxGetJSON(url: string, resultSelector?: (data: T) => R, headers?: Object): Observable { + const finalResultSelector = resultSelector ? (res: AjaxResponse) => resultSelector(res.response) : null; + return new AjaxObservable({ 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. * @@ -60,13 +93,27 @@ const createXHRDefault = (): XMLHttpRequest => { * @returns {Observable} An observable sequence containing the XMLHttpRequest. */ export class AjaxObservable extends Observable { - static create(options: string | any): Observable { + 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 create; + })(); + + static create2(options: string | AjaxRequest): Observable { return new AjaxObservable(options); } private request: AjaxRequest; - constructor(options: string | any) { + constructor(options: string | AjaxRequest) { super(); const request: AjaxRequest = { @@ -88,6 +135,7 @@ export class AjaxObservable extends Observable { } } } + request.headers = request.headers || {}; if (!request.crossDomain && !request.headers['X-Requested-With']) { request.headers['X-Requested-With'] = 'XMLHttpRequest'; diff --git a/src/observable/dom/get.ts b/src/observable/dom/get.ts deleted file mode 100644 index e70a274ebd..0000000000 --- a/src/observable/dom/get.ts +++ /dev/null @@ -1,12 +0,0 @@ -import {Observable} from '../../Observable'; -import {AjaxObservable} from './ajax'; - -function get(url: string | any): Observable { - if (typeof url === 'string') { - return new AjaxObservable({ url }); - } else { - return new AjaxObservable(url); - } -} - -export { AjaxObservable, get }; diff --git a/src/observable/dom/getJSON.ts b/src/observable/dom/getJSON.ts deleted file mode 100644 index 332c6798d7..0000000000 --- a/src/observable/dom/getJSON.ts +++ /dev/null @@ -1,12 +0,0 @@ -import {root} from '../../util/root'; -import {Observable} from '../../Observable'; -import {AjaxObservable} from './ajax'; - -function getJSON(url: string | any): Observable { - if (!root.JSON && typeof root.JSON.parse !== 'function') { - throw new TypeError('JSON is not supported in your runtime.'); - } - return new AjaxObservable({ url, emitType: 'json', responseType: 'json' }); -} - -export { AjaxObservable, getJSON }; diff --git a/src/observable/dom/post.ts b/src/observable/dom/post.ts deleted file mode 100644 index 25f1b40696..0000000000 --- a/src/observable/dom/post.ts +++ /dev/null @@ -1,13 +0,0 @@ -import {Observable} from '../../Observable'; -import {AjaxObservable} from './ajax'; - -function post(url: string | any, body?: any): Observable { - if (typeof url === 'string') { - return new AjaxObservable({ url, body, method: 'POST' }); - } else { - ( url).method = 'POST'; - return new AjaxObservable(( url)); - } -} - -export { AjaxObservable, post };