Skip to content

Commit 5b5ffe7

Browse files
committed
docs(Http): add docs for Http lib
Fixes angular#2442
1 parent e68e69e commit 5b5ffe7

File tree

18 files changed

+556
-216
lines changed

18 files changed

+556
-216
lines changed

docs/public-docs-package/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ module.exports = new Package('angular-public', [basePackage])
1010
'angular2/core.ts',
1111
'angular2/di.ts',
1212
'angular2/directives.ts',
13+
'angular2/http.ts',
1314
'angular2/forms.ts',
14-
'angular2/router.js',
15+
'angular2/router.ts',
1516
'angular2/test.ts',
1617
'angular2/pipes.ts'
1718
];

modules/angular2/angular2.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export * from './annotations';
44
export * from './directives';
55
export * from './forms';
66
export * from './di';
7+
export * from './http';
78
export {Observable, EventEmitter} from 'angular2/src/facade/async';
89
export * from 'angular2/src/render/api';
910
export {DomRenderer, DOCUMENT_TOKEN} from 'angular2/src/render/dom/dom_renderer';

modules/angular2/http.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
library angular2.http;

modules/angular2/http.ts

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,41 @@
1+
/**
2+
* @module
3+
* @public
4+
* @description
5+
* The http module provides services to perform http requests. To get started, see the {@link Http}
6+
* class.
7+
*/
18
import {bind, Binding} from 'angular2/di';
29
import {Http, HttpFactory} from './src/http/http';
3-
import {XHRBackend} from 'angular2/src/http/backends/xhr_backend';
10+
import {XHRBackend, XHRConnection} from 'angular2/src/http/backends/xhr_backend';
411
import {BrowserXHR} from 'angular2/src/http/backends/browser_xhr';
5-
import {BaseRequestOptions} from 'angular2/src/http/base_request_options';
12+
import {BaseRequestOptions, RequestOptions} from 'angular2/src/http/base_request_options';
613

7-
export {Http};
14+
export {MockConnection, MockBackend} from 'angular2/src/http/backends/mock_backend';
15+
export {Request} from 'angular2/src/http/static_request';
16+
export {Response} from 'angular2/src/http/static_response';
17+
18+
export {Http, XHRBackend, XHRConnection, BaseRequestOptions, RequestOptions, HttpFactory};
19+
export {IHttp} from 'angular2/src/http/interfaces';
20+
export {Headers} from 'angular2/src/http/headers';
21+
22+
/**
23+
* Provides a basic set of injectables to use the {@link Http} service in any application.
24+
*
25+
* #Example
26+
*
27+
* ```
28+
* import {httpInjectables, Http} from 'angular2/http';
29+
* @Component({selector: 'http-app', appInjector: [httpInjectables]})
30+
* @View({template: '{{data}}'})
31+
* class MyApp {
32+
* constructor(http:Http) {
33+
* http.request('data.txt').subscribe(res => this.data = res.text());
34+
* }
35+
* }
36+
* ```
37+
*
38+
*/
839
export var httpInjectables: List<any> = [
940
bind(BrowserXHR)
1041
.toValue(BrowserXHR),

modules/angular2/src/http/backends/mock_backend.ts

Lines changed: 161 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,40 @@ import {Injectable} from 'angular2/di';
22
import {Request} from 'angular2/src/http/static_request';
33
import {Response} from 'angular2/src/http/static_response';
44
import {ReadyStates} from 'angular2/src/http/enums';
5+
import {Connection, ConnectionBackend} from 'angular2/src/http/interfaces';
56
import * as Rx from 'rx';
67

78
/**
8-
* Connection represents a request and response for an underlying transport, like XHR or mock.
9-
* The mock implementation contains helper methods to respond to connections within tests.
10-
* API subject to change and expand.
9+
*
10+
* Connection class used by MockBackend
11+
*
12+
* This class is typically not instantiated directly, but instances can be retrieved by subscribing
13+
*to the `connections` Observable of
14+
* {@link MockBackend} in order to mock responses to requests.
15+
*
1116
**/
12-
export class Connection {
17+
export class MockConnection implements Connection {
18+
// TODO Name `readyState` should change to be more generic, and states could be made to be more
19+
// descriptive than XHR states.
1320
/**
14-
* Observer to call on download progress, if provided in config.
15-
**/
16-
downloadObserver: Rx.Observer<Response>;
21+
* Describes the state of the connection, based on `XMLHttpRequest.readyState`, but with
22+
* additional states. For example, state 5 indicates an aborted connection.
23+
*/
24+
readyState: ReadyStates;
1725

1826
/**
19-
* TODO
20-
* Name `readyState` should change to be more generic, and states could be made to be more
21-
* descriptive than XHR states.
22-
**/
23-
24-
readyState: ReadyStates;
27+
* {@link Request} instance used to create the connection.
28+
*/
2529
request: Request;
30+
31+
/**
32+
* [RxJS
33+
* Observable](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/observable.md)
34+
* of {@link Response}. Can be subscribed to in order to be notified when a response is available.
35+
*/
2636
response: Rx.Subject<Response>;
2737

2838
constructor(req: Request) {
29-
// State
3039
if (Rx.hasOwnProperty('default')) {
3140
this.response = new ((<any>Rx).default.Rx.Subject)();
3241
} else {
@@ -38,15 +47,29 @@ export class Connection {
3847
this.dispose = this.dispose.bind(this);
3948
}
4049

50+
/**
51+
* Changes the `readyState` of the connection to a custom state of 5 (cancelled).
52+
*/
4153
dispose() {
4254
if (this.readyState !== ReadyStates.DONE) {
4355
this.readyState = ReadyStates.CANCELLED;
4456
}
4557
}
4658

4759
/**
48-
* Called after a connection has been established.
49-
**/
60+
* Sends a mock response to the connection. This response is the value that is emitted to the
61+
* `Observable` returned by {@link Http}.
62+
*
63+
* #Example
64+
*
65+
* ```
66+
* var connection;
67+
* backend.connections.subscribe(c => connection = c);
68+
* http.request('data.json').subscribe(res => console.log(res.text()));
69+
* connection.mockRespond(new Response('fake response')); //logs 'fake response'
70+
* ```
71+
*
72+
*/
5073
mockRespond(res: Response) {
5174
if (this.readyState >= ReadyStates.DONE) {
5275
throw new Error('Connection has already been resolved');
@@ -56,13 +79,24 @@ export class Connection {
5679
this.response.onCompleted();
5780
}
5881

82+
/**
83+
* Not yet implemented!
84+
*
85+
* Sends the provided {@link Response} to the `downloadObserver` of the `Request`
86+
* associated with this connection.
87+
*/
5988
mockDownload(res: Response) {
60-
this.downloadObserver.onNext(res);
61-
if (res.bytesLoaded === res.totalBytes) {
62-
this.downloadObserver.onCompleted();
63-
}
89+
// this.request.downloadObserver.onNext(res);
90+
// if (res.bytesLoaded === res.totalBytes) {
91+
// this.request.downloadObserver.onCompleted();
92+
// }
6493
}
6594

95+
// TODO(jeffbcross): consider using Response type
96+
/**
97+
* Emits the provided error object as an error to the {@link Response} observable returned
98+
* from {@link Http}.
99+
*/
66100
mockError(err?) {
67101
// Matches XHR semantics
68102
this.readyState = ReadyStates.DONE;
@@ -71,35 +105,135 @@ export class Connection {
71105
}
72106
}
73107

108+
/**
109+
* A mock backend for testing the {@link Http} service.
110+
*
111+
* This class can be injected in tests, and should be used to override bindings
112+
* to other backends, such as {@link XHRBackend}.
113+
*
114+
* #Example
115+
*
116+
* ```
117+
* import {MockBackend, DefaultOptions, Http} from 'angular2/http';
118+
* it('should get some data', inject([AsyncTestCompleter], (async) => {
119+
* var connection;
120+
* var injector = Injector.resolveAndCreate([
121+
* MockBackend,
122+
* bind(Http).toFactory((backend, defaultOptions) => {
123+
* return new Http(backend, defaultOptions)
124+
* }, [MockBackend, DefaultOptions])]);
125+
* var http = injector.get(Http);
126+
* var backend = injector.get(MockBackend);
127+
* //Assign any newly-created connection to local variable
128+
* backend.connections.subscribe(c => connection = c);
129+
* http.request('data.json').subscribe((res) => {
130+
* expect(res.text()).toBe('awesome');
131+
* async.done();
132+
* });
133+
* connection.mockRespond(new Response('awesome'));
134+
* }));
135+
* ```
136+
*
137+
* This method only exists in the mock implementation, not in real Backends.
138+
**/
74139
@Injectable()
75-
export class MockBackend {
76-
connections: Rx.Subject<Connection>;
77-
connectionsArray: Array<Connection>;
78-
pendingConnections: Rx.Observable<Connection>;
140+
export class MockBackend implements ConnectionBackend {
141+
/**
142+
* [RxJS
143+
* Subject](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/subjects/subject.md)
144+
* of {@link MockConnection} instances that have been created by this backend. Can be subscribed
145+
* to in order to respond to connections.
146+
*
147+
* #Example
148+
*
149+
* ```
150+
* import {MockBackend, Http, BaseRequestOptions} from 'angular2/http';
151+
* import {Injector} from 'angular2/di';
152+
*
153+
* it('should get a response', () => {
154+
* var connection; //this will be set when a new connection is emitted from the backend.
155+
* var text; //this will be set from mock response
156+
* var injector = Injector.resolveAndCreate([
157+
* MockBackend,
158+
* bind(Http).toFactory(backend, options) {
159+
* return new Http(backend, options);
160+
* }, [MockBackend, BaseRequestOptions]]);
161+
* var backend = injector.get(MockBackend);
162+
* var http = injector.get(Http);
163+
* backend.connections.subscribe(c => connection = c);
164+
* http.request('something.json').subscribe(res => {
165+
* text = res.text();
166+
* });
167+
* connection.mockRespond(new Response('Something'));
168+
* expect(text).toBe('Something');
169+
* });
170+
* ```
171+
*
172+
* This property only exists in the mock implementation, not in real Backends.
173+
*/
174+
connections: Rx.Subject<MockConnection>;
175+
176+
/**
177+
* An array representation of `connections`. This array will be updated with each connection that
178+
* is created by this backend.
179+
*
180+
* This property only exists in the mock implementation, not in real Backends.
181+
*/
182+
connectionsArray: Array<MockConnection>;
183+
/**
184+
* [Observable](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/observable.md)
185+
* of {@link MockConnection} instances that haven't yet been resolved (i.e. with a `readyState`
186+
* less than 4). Used internally to verify that no connections are pending via the
187+
* `verifyNoPendingRequests` method.
188+
*
189+
* This property only exists in the mock implementation, not in real Backends.
190+
*/
191+
pendingConnections: Rx.Observable<MockConnection>;
79192
constructor() {
193+
var Observable;
80194
this.connectionsArray = [];
81195
if (Rx.hasOwnProperty('default')) {
82196
this.connections = new (<any>Rx).default.Rx.Subject();
197+
Observable = (<any>Rx).default.Rx.Observable;
83198
} else {
84-
this.connections = new Rx.Subject<Connection>();
199+
this.connections = new Rx.Subject<MockConnection>();
200+
Observable = Rx.Observable;
85201
}
86202
this.connections.subscribe(connection => this.connectionsArray.push(connection));
87-
this.pendingConnections = this.connections.filter((c) => c.readyState < ReadyStates.DONE);
203+
this.pendingConnections =
204+
Observable.fromArray(this.connectionsArray).filter((c) => c.readyState < ReadyStates.DONE);
88205
}
89206

207+
/**
208+
* Checks all connections, and raises an exception if any connection has not received a response.
209+
*
210+
* This method only exists in the mock implementation, not in real Backends.
211+
*/
90212
verifyNoPendingRequests() {
91213
let pending = 0;
92214
this.pendingConnections.subscribe((c) => pending++);
93215
if (pending > 0) throw new Error(`${pending} pending connections to be resolved`);
94216
}
95217

218+
/**
219+
* Can be used in conjunction with `verifyNoPendingRequests` to resolve any not-yet-resolve
220+
* connections, if it's expected that there are connections that have not yet received a response.
221+
*
222+
* This method only exists in the mock implementation, not in real Backends.
223+
*/
96224
resolveAllConnections() { this.connections.subscribe((c) => c.readyState = 4); }
97225

226+
/**
227+
* Creates a new {@link MockConnection}. This is equivalent to calling `new
228+
* MockConnection()`, except that it also will emit the new `Connection` to the `connections`
229+
* observable of this `MockBackend` instance. This method will usually only be used by tests
230+
* against the framework itself, not by end-users.
231+
*/
98232
createConnection(req: Request) {
99233
if (!req || !(req instanceof Request)) {
100234
throw new Error(`createConnection requires an instance of Request, got ${req}`);
101235
}
102-
let connection = new Connection(req);
236+
let connection = new MockConnection(req);
103237
this.connections.onNext(connection);
104238
return connection;
105239
}

modules/angular2/src/http/backends/xhr_backend.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,21 @@ import {Injectable} from 'angular2/di';
77
import {BrowserXHR} from './browser_xhr';
88
import * as Rx from 'rx';
99

10+
/**
11+
* Creates connections using `XMLHttpRequest`. Given a fully-qualified
12+
* request, an `XHRConnection` will immediately create an `XMLHttpRequest` object and send the
13+
* request.
14+
*
15+
* This class would typically not be created or interacted with directly inside applications, though
16+
* the {@link MockConnection} may be interacted with in tests.
17+
*/
1018
export class XHRConnection implements Connection {
1119
request: Request;
20+
/**
21+
* Response
22+
* [Subject](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/subjects/subject.md)
23+
* which emits a single {@link Response} value on load event of `XMLHttpRequest`.
24+
*/
1225
response: Rx.Subject<Response>;
1326
readyState: ReadyStates;
1427
private _xhr;
@@ -20,6 +33,7 @@ export class XHRConnection implements Connection {
2033
this.response = new Rx.Subject<Response>();
2134
}
2235
this._xhr = new NativeConstruct();
36+
// TODO(jeffbcross): implement error listening/propagation
2337
this._xhr.open(RequestMethods[req.method], req.url);
2438
this._xhr.addEventListener(
2539
'load',
@@ -28,9 +42,38 @@ export class XHRConnection implements Connection {
2842
this._xhr.send(this.request.text());
2943
}
3044

45+
/**
46+
* Calls abort on the underlying XMLHttpRequest.
47+
*/
3148
dispose(): void { this._xhr.abort(); }
3249
}
3350

51+
/**
52+
* Creates {@link XHRConnection} instances.
53+
*
54+
* This class would typically not be used by end users, but could be
55+
* overridden if a different backend implementation should be used,
56+
* such as in a node backend.
57+
*
58+
* #Example
59+
*
60+
* ```
61+
* import {Http, MyNodeBackend, httpInjectables, BaseRequestOptions} from 'angular2/http';
62+
* @Component({
63+
* appInjector: [
64+
* httpInjectables,
65+
* bind(Http).toFactory((backend, options) => {
66+
* return new Http(backend, options);
67+
* }, [MyNodeBackend, BaseRequestOptions])]
68+
* })
69+
* class MyComponent {
70+
* constructor(http:Http) {
71+
* http('people.json').subscribe(res => this.people = res.json());
72+
* }
73+
* }
74+
* ```
75+
*
76+
**/
3477
@Injectable()
3578
export class XHRBackend implements ConnectionBackend {
3679
constructor(private _NativeConstruct: BrowserXHR) {}

0 commit comments

Comments
 (0)