Open Naixor opened 8 years ago
问题描述补充,虽然直接写response._body
或者super._body
,但是通常这样ts会报错。。。有木有看起来更优雅一点的解决办法呢?
这个已解决,也贴出来供其他人借鉴: 自己写一个XHRConnection,然后依赖注入进去。
import {Injectable} from 'angular2/core';
import {isPresent, isString, Json} from 'angular2/src/facade/lang';
import {Connection, XHRConnection, Request, ReadyState, BrowserXhr, ResponseOptions, RequestMethod, Headers, ResponseType, ConnectionBackend } from 'angular2/http';
import {isSuccess, isJsObject, getResponseURL} from 'angular2/src/http/http_utils';
import {Observable} from 'rxjs/Observable';
import {Observer} from 'rxjs/Observer';
class MiResponseOptions extends ResponseOptions {
statusText: string;
type: any;
merge(options?): MiResponseOptions {
return new MiResponseOptions({
body: isPresent(options) && isPresent(options.body) ? options.body : this.body,
status: isPresent(options) && isPresent(options.status) ? options.status : this.status,
headers: isPresent(options) && isPresent(options.headers) ? options.headers : this.headers,
statusText: isPresent(options) && isPresent(options.statusText) ? options.statusText :
this.statusText,
type: isPresent(options) && isPresent(options.type) ? options.type : this.type,
url: isPresent(options) && isPresent(options.url) ? options.url : this.url,
});
}
}
class MiResponse {
type: ResponseType;
ok: boolean;
url: string;
status: number;
statusText: string;
bytesLoaded: number;
totalBytes: number;
headers: Headers;
// TODO: Support ArrayBuffer, JSON, FormData, Blob
private _body: string | Object;
constructor(responseOptions: MiResponseOptions) {
this._body = responseOptions.body;
this.status = responseOptions.status;
this.statusText = responseOptions.statusText;
this.headers = responseOptions.headers;
this.type = responseOptions.type;
this.url = responseOptions.url;
}
blob(): any {
return this._body;
}
json(): any {
var jsonResponse: string | Object;
if (isJsObject(this._body)) {
jsonResponse = this._body;
} else if (isString(this._body)) {
jsonResponse = Json.parse(<string>this._body);
}
return jsonResponse;
}
text(): string { return this._body.toString(); }
arrayBuffer(): any {
return this._body;
}
}
class MiXHRConnection implements Connection {
request: Request;
response: Observable<MiResponse>;
readyState: ReadyState;
private _responseType: any;
constructor(req: Request, browserXHR: BrowserXhr, baseResponseOptions?: MiResponseOptions) {
// console.log(baseResponseOptions);
this._responseType = req.headers.get('responseType');
if (this._responseType) {
req.headers.delete('responseType');
}
this.request = req;
this.response = new Observable((responseObserver: Observer<MiResponse>) => {
let _xhr: XMLHttpRequest = browserXHR.build();
// 添加blob/arraybuffer responseType到xhr
switch (this._responseType) {
case 'blob':
case 'arraybuffer':
_xhr.responseType = this._responseType;
break;
default:
break;
}
_xhr.open(RequestMethod[req.method].toUpperCase(), req.url);
let onLoad = () => {
let body = isPresent(_xhr.response) ? _xhr.response : _xhr.responseText;
let headers = Headers.fromResponseHeaderString(_xhr.getAllResponseHeaders());
let url = getResponseURL(_xhr);
let status: number = _xhr.status === 1223 ? 204 : _xhr.status;
if (status === 0) {
status = body ? 200 : 0;
}
var responseOptions = new MiResponseOptions({body, status, headers, url});
if (isPresent(baseResponseOptions)) {
responseOptions = baseResponseOptions.merge(responseOptions);
}
let response = new MiResponse(responseOptions);
if (isSuccess(status)) {
responseObserver.next(response);
responseObserver.complete();
return;
}
responseObserver.error(response);
};
let onError = (err: any) => {
var responseOptions = new MiResponseOptions({body: err, type: ResponseType.Error});
if (isPresent(baseResponseOptions)) {
responseOptions = baseResponseOptions.merge(responseOptions);
}
responseObserver.error(new MiResponse(responseOptions));
};
let onProgress = (event: any) => {
console.log(event);
}
if (isPresent(req.headers)) {
req.headers.forEach((values, name) => _xhr.setRequestHeader(name, values.join(',')));
}
_xhr.addEventListener('load', onLoad);
_xhr.addEventListener('error', onError);
_xhr.addEventListener('progress', onProgress);
_xhr.send(this.request.text());
return () => {
_xhr.removeEventListener('load', onLoad);
_xhr.removeEventListener('error', onError);
_xhr.removeEventListener('progress', onProgress);
_xhr.abort();
};
});
}
}
@Injectable()
export class MiXHRBackend implements ConnectionBackend {
constructor(private _browserXHR: BrowserXhr, private _baseResponseOptions: ResponseOptions) {}
createConnection(request: Request): MiXHRConnection {
return new MiXHRConnection(request, this._browserXHR, new MiResponseOptions(this._baseResponseOptions));
}
}
然后调用:
@Component({
...
providers: [
HTTP_PROVIDERS,
provide(XHRBackend , {
useClass: MiXHRBackend
}}]
})
class Test {
constructor(@Inject(Http) http) {
let header = new Headers();
header.append('Accept', 'image/webp,image/*,*/*;q=0.8');
header.append('responseType', 'arraybuffer');
http.get( url , { headers: header }).subscribe(response => {
console.log(response.blob()); // return _body
console.log(response.arrayBuffer()); // return _body
});
}
}
如图,再写一个图片组件时需要用
ajax
请求图片,希望ajax请求的图片返回arraybuffer
,这时Response
并不支持直接返回,只能使用response._body
,但是这个_body
又是私有变量,于是,我如何扩写Response
,来实现它目前尚未实现的blob()
和arrayBuffer()
呢?