如何中止来自 Observable 的 Ajax 请求?
How to abort an Ajax request from an Observable?
我的代码包含我用来将文件上传到我的 PHP 服务器的这个简单函数(xhr
请求嵌套在 RxJS/Observable
中):
fileUpload(file: File): Observable<any> {
return new Observable( observer => {
let xhr:XMLHttpRequest = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
observer.next(<any>JSON.parse(xhr.response));
} else {
observer.error(xhr.response);
observer.complete();
}
}
};
xhr.open('POST', '__BACKEND__?action=file-upload', true);
var formData = new FormData();
formData.append('file', file, file.name);
xhr.send(formData);
});
}
它是完全可用的,但现在我还想向它添加某种取消机制。
仅仅取消订阅 Observable 是行不通的,因为我需要以某种方式调用 xhr.abort()
否则我会在大量上传中浪费宝贵的资源。
是否可以通过修改此代码获得一个优雅的解决方案,或者我做错了,因为我正在使用 RxJS/Observable
来完成此任务?
Return xhr 对象并在另一个可观察对象中对其执行中止。
var uploadObservable = fileUpload();
var uploadRequest;
uploadObservable.subscribe(
function (x) {
uploadRequest = x;
},
function (err) {
console.log('Error: %s', err);
},
function () {
console.log('Completed');
});
var cancelBtn = Rx.Observable.fromEvent(cancelBtn, 'click');
cancelBtn.subscribe(
function (x) {
uploadRequest.abort();
},
function (err) {
console.log('Error: %s', err);
},
function () {
console.log('Completed');
});
或者
fileUpload()
.flatMap(function(xhr) {
Rx.Observable.fromEvent(cancelBtn, 'click').subscribe(function() {xhr.abort()})
})
.subscribe(...);
创建 Observable
时,您可以通过从构建器函数返回 Subscription
或 function
来指定取消订阅行为:
fileUpload(file: File): Observable<any> {
return new Observable( observer => {
let xhr:XMLHttpRequest = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
observer.next(<any>JSON.parse(xhr.response));
observer.complete();
} else {
observer.error(xhr.response);
}
}
};
xhr.open('POST', '__BACKEND__?action=file-upload', true);
var formData = new FormData();
formData.append('file', file, file.name);
xhr.send(formData);
//Return the tear down logic.
//You may also want to check here that it has not already completed
//Since this gets called in all cases when the `Subscription` terminates
return () => xhr.abort();
});
}
请求将中止并进入取消订阅调用。
有关详细信息,请参阅 AjaxObservable.unsubscribe 来源:
https://github.com/ReactiveX/rxjs/blob/441d52208df8b9247b01f8ca3993e3a7b0870b10/src/internal/observable/dom/AjaxObservable.ts#L423
我的代码包含我用来将文件上传到我的 PHP 服务器的这个简单函数(xhr
请求嵌套在 RxJS/Observable
中):
fileUpload(file: File): Observable<any> {
return new Observable( observer => {
let xhr:XMLHttpRequest = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
observer.next(<any>JSON.parse(xhr.response));
} else {
observer.error(xhr.response);
observer.complete();
}
}
};
xhr.open('POST', '__BACKEND__?action=file-upload', true);
var formData = new FormData();
formData.append('file', file, file.name);
xhr.send(formData);
});
}
它是完全可用的,但现在我还想向它添加某种取消机制。
仅仅取消订阅 Observable 是行不通的,因为我需要以某种方式调用 xhr.abort()
否则我会在大量上传中浪费宝贵的资源。
是否可以通过修改此代码获得一个优雅的解决方案,或者我做错了,因为我正在使用 RxJS/Observable
来完成此任务?
Return xhr 对象并在另一个可观察对象中对其执行中止。
var uploadObservable = fileUpload();
var uploadRequest;
uploadObservable.subscribe(
function (x) {
uploadRequest = x;
},
function (err) {
console.log('Error: %s', err);
},
function () {
console.log('Completed');
});
var cancelBtn = Rx.Observable.fromEvent(cancelBtn, 'click');
cancelBtn.subscribe(
function (x) {
uploadRequest.abort();
},
function (err) {
console.log('Error: %s', err);
},
function () {
console.log('Completed');
});
或者
fileUpload()
.flatMap(function(xhr) {
Rx.Observable.fromEvent(cancelBtn, 'click').subscribe(function() {xhr.abort()})
})
.subscribe(...);
创建 Observable
时,您可以通过从构建器函数返回 Subscription
或 function
来指定取消订阅行为:
fileUpload(file: File): Observable<any> {
return new Observable( observer => {
let xhr:XMLHttpRequest = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
observer.next(<any>JSON.parse(xhr.response));
observer.complete();
} else {
observer.error(xhr.response);
}
}
};
xhr.open('POST', '__BACKEND__?action=file-upload', true);
var formData = new FormData();
formData.append('file', file, file.name);
xhr.send(formData);
//Return the tear down logic.
//You may also want to check here that it has not already completed
//Since this gets called in all cases when the `Subscription` terminates
return () => xhr.abort();
});
}
请求将中止并进入取消订阅调用。 有关详细信息,请参阅 AjaxObservable.unsubscribe 来源: https://github.com/ReactiveX/rxjs/blob/441d52208df8b9247b01f8ca3993e3a7b0870b10/src/internal/observable/dom/AjaxObservable.ts#L423