I have function like this, it just upload image with xhr request:
public uploadAvatar(avatarFile, callback) {
return new Promise((resolve, reject) => {
let formData: any = new FormData();
let url = 'avatar';
let imgArr = "avatar";
let xhr = new XMLHttpRequest();
formData.append(imgArr, avatarFile, avatarFile.name);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
resolve(JSON.parse(xhr.response));
callback('success');
} else {
reject(xhr.response);
callback('error');
}
}
};
xhr.open("POST", environment.baseUrl + url, true);
xhr.setRequestHeader('Auth', this._auth.getToken());
xhr.send(formData);
});
}
How can I return Observable insted Promise?
eddyP23's answer is almost correct but there are two more things.
One key difference between Observables and Promises is that Observables can be canceled in contrast to Promises. This is very relevant to your situation where you're using XHR to perform AJAX calls. While XMLHttpRequest can be aborted using the abort()
function you can't abort pending Promise.
However with Observables you can. When you complete or unsubscribe an Observable you can also cancel the XHR object because you know you're not interested in it.
See also: https://medium.com/@benlesh/promise-cancellation-is-dead-long-live-promise-cancellation-c6601f1f5082
So you function when transformed from using Promises to Observables should look like this:
public uploadAvatar(avatarFile, callback) {
return Rx.Observable.create(function (observer) {
...
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
observer.onNext(JSON.parse(xhr.response));
observer.onCompleted();
} else {
observer.onError(xhr.response);
}
}
return () => {
xhr.abort();
};
}
)
Notice that we're returning a function which is used when disposing the Observable. For more information about Observable.create
have a look at http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#static-method-create
The second thing is that if you don't care about aborting the XHR you can just use Promises. RxJS 5 treats Promises the same way as Observables. Notice that Observable.from()
takes as a parameter some ObservableInput
which is in detail described here: http://reactivex.io/rxjs/class/es6/MiscJSDoc.js~ObservableInputDoc.html
For you it means that you can just call uploadAvatar()
as is and the Promise returned is going to be turned into an Observables automatically:
Observable.from(uploadAvatar(...))
.subscribe(...)
Something like this should work
public uploadAvatar(avatarFile, callback) {
return Rx.Observable.create(function (observer) {
let formData: any = new FormData();
let url = 'avatar';
let imgArr = "avatar";
let xhr = new XMLHttpRequest();
formData.append(imgArr, avatarFile, avatarFile.name);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
observer.onNext(JSON.parse(xhr.response));
observer.onCompleted();
callback('success');
} else {
observer.onError(xhr.response);
callback('error');
}
}
};
xhr.open("POST", environment.baseUrl + url, true);
xhr.setRequestHeader('Auth', this._auth.getToken());
xhr.send(formData);
});
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With