Unsubscribe in rxjs - rxjs

I'm new to rxjs.
what is the problem with this code that subscribe method not work correctly.
this.http.postReq(this.api, data)
.subscribe((value) => {
this.toastr.success(value, "Successfull");
this.isLoading = false;
}, (err) => {
this.toastr.error(err.error, "Error")
this.isLoading = false;
}).unsubscribe();
}
but when remove ".unsubscribe()" its work correctly.
an example that work correctly in this manner.

To do this :
let someSubscription = this.http.postReq(this.api, data)
.subscribe((value) => {
this.toastr.success(value, "Successfull");
this.isLoading = false;
someSubscription.unsubscribe();
}, (err) => {
this.toastr.error(err.error, "Error")
this.isLoading = false;
});
So now , your request is unsubscribed after getting the response (which you want) .

Related

How to throw error after subscription timeout?

I'm simply trying to display in the view ( when for example user's connection is too slow and results won't come from subscription) after 30 seconds.
I'm surely missing something because even when results all arrive, the console timeout error message is still appearing.
This is what I tried:
searchInfo() {
this.isLoading = true;
this.info= [];
const source = this.infoService.searchInfo('help');
source.pipe(
timeout(30000),
takeUntil(this.onDestroy$)
).subscribe((infoTable: infoTableContent) => {
this.info.push(infoTable);
this.isLoading = false;
}),
(err) => {
this.isLoading = false;
console.log(err, 'Sorry, ...') //not working
}
I want to be able to display a message like "Sorry, took too long to retrieve data" after 30 seconds of trying to subscribe.
Thank you all in advance
You have an extra ) right after your next callback in the subscribe.
Therefore, your error callback is ignored.
.subscribe((infoTable: infoTableContent) => {
this.info.push(infoTable);
this.isLoading = false;
}), // <-- This paranthesis closes the subscribe method
The following works as expected
.subscribe(
(infoTable: infoTableContent) => {
this.info.push(infoTable);
this.isLoading = false;
},
(err) => {
this.isLoading = false;
console.log(err, 'Sorry, ...');
}
);
When I run this with Mocked Services it runs just fine for me:
const mockService = {
searchInfo: msg => NEVER.pipe(startWith({key: msg}))
};
const onDestroy$ = timer(5000);
let isLoading = true;
const info = [];
mockService.searchInfo('help').pipe(
timeout(1000),
takeUntil(onDestroy$)
).subscribe({
next: (mockTable: any) => {
info.push(mockTable);
isLoading = false;
},
error: err => {
isLoading = false;
console.log('Sorry, ...', err);
}
});
I suspect your bug might be due to miss-formatting (brackets in the wrong place etc)

this2.$dispatch is not a function

I'm trying to use the dispatch function in vue.js like this.
But I'm getting an error saying this2.$dispatch is not a function...like you can see on the screenshot
message.vue
export default {
data(){
return{
message:'',
isLoading:false,
}
},
methods:{
addMessage(){
if(this.message !=''){
this.sendData();
} else{
this.$fire({
title: "Error",
text: "Enter some text.",
type: "error",
timer: 3000
}).then(r => {
console.log(r.value);
});
setTimeout(() => {
this.isLoading = false
},700)
}
},
sendData(){
this.isLoading = true;
this.$http.post('/add-message' , {message:this.message, id_rooms:this.$route.params.id_rooms}).then((response) => {
console.log(response.json());
if(response.body != 'Error'){
this.message = '';
this.$dispatch('new_message', response.json());
} else{
this.isLoading = false;
}
}, (response) =>{
});
}
}
}
and then I'm trying to get it out like this
chat.vue
export default {
components:{
get_message:getMessage,
add_message:addMessage,
},
data(){
return{
messages:[]
}
},
events:{
'new_message':function(data){
this.messages.push(data);
}
}
}
I'm facing this error in console...any ideas how can I solve this ?
update
If your store is registered with Vue, it seems like it should work. If your $dispatch works outside of the promise, you can try storing this context in another variable
sendData(){
this.isLoading = true;
const that = this;
this.$http
.post('/add-message' , {message:this.message, id_rooms:this.$route.params.id_rooms})
.then((response) => {
console.log(response.json());
if(response.body != 'Error'){
that.message = '';
that.$dispatch('new_message', response.json());
} else{
that.isLoading = false;
}
}, (response) =>{
});
}
or just the $dispatch
sendData(){
this.isLoading = true;
const $dispatch = this.$dispatch;
this.$http
.post('/add-message' , {message:this.message, id_rooms:this.$route.params.id_rooms})
.then((response) => {
console.log(response.json());
if(response.body != 'Error'){
this.message = '';
$dispatch('new_message', response.json());
} else{
this.isLoading = false;
}
}, (response) =>{
});
}
Taking a guess here, but try calling this instead
this.$store.dispatch('new_message', response.json());
alternatively, your issue could be a scope issue (seeing that this is called from a promise)
if you have a function declared like this in the promise handler then(function(response){this.$store.dispatch('new_message', response.json());}) it might be due to scope
instead you could try using arrow function
then((response) => {
this.$store.dispatch('new_message', response.json());
})

Vue js PATCH http://127.0.0.1:8000/api/auth/profile 401 (Unauthorized)

I have a modal where I can create edit users. But when I click on the submit button I got a 401 error.
and I want to change the name without update page
The method looks like this:
if(token){
this.preformUpdate();
}
},
methods: {
preformUpdate: function() {
this.loading = true;
this.msgupdate = "Updated your profile";
this.alert = true;
axios
.patch("/profile", {
name: this.name,
token: this.token
})
.then(response => {
const name = localStorage.setItem("name", response.data.user.name);
this.email = localStorage.getItem("email");
console.log(response.data.user.name);
this.loading = false;
})
.catch(error => {
console.log(error);
this.error = error.message;
this.loading = false;
});
}
}

Promise all issue ( I get empty response )

How can I solve it? When I try to get a result from promise all, I get an empty array.
async function getMessage(arr) {
let response = [];
for (let count = 0; count < arr.length; count++) {
let protocol = await arr[count].link.split(':')[0];
if (protocol === 'http') {
await http.get(arr[count].link, async (res) => {
response.push(`${arr[count].link} - ${res.statusCode}\n`);
});
} else {
await https.get(arr[count].link, async (res) => {
response.push(`${arr[count].link} - ${res.statusCode}\n`);
});
}
}
return Promise.all(response)
.then((data) => {
//data === []
return data;
});
}
The await operator is used to wait for a Promise.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await
I assume you're using node's native http and https module. It's true they're async functions, but they cannot be used with await straight, since they're using callback not Promise.
Afaik, you can either manually "promisify" it with util.promisify, or use some 3rd party like isomorphic-fetch which already promisified it for you.
Example:
const sayHelloWithoutPromise = () => {
setTimeout(() => console.log('hello'), 0)
}
(async function() {
await sayHelloWithoutPromise()
console.log('world!')
})()
const sayHelloWithPromise = () => {
return new Promise(r =>
setTimeout(() => r(console.log('hello')), 0)
)
}
(async function() {
await sayHelloWithPromise()
console.log('world!')
})()

How to handle Google OAuth flow via redux-saga

I am trying to implement Google OAuth 2 with with redux saga.
I have a watcher in my saga listening for GOOGLE_AUTH action which then executes googleLogin
function *watchGoogleAuth() {
yield *takeLatest(GOOGLE_AUTH, googleLogin)
}
function *googleLogin() {
const id_token = yield call(GoogleSignIn);
console.log(id_token);
const response = yield call(HttpHelper, 'google_token', 'POST', id_token, null);
console.log(response);
}
The implementation for GoogleSignIn is in apis.js
export function GoogleSignIn() {
const GoogleAuth = window.gapi.auth2.getAuthInstance();
GoogleAuth.signIn({scope: 'profile email'})
.then(
(res) => {
const GoogleUser = GoogleAuth.currentUser.get();
return {
id_token: GoogleUser.getAuthResponse().id_token
};
},
(err) => {
console.log(err)
}
)
}
But saga doesn't seem to wait for the GoogleSignIn to complete. As soon as OAuth consent screen pops up, saga proceeds executing the console.log without waiting for google signin promise to return actual data.
Is there any better way to handle this situation? Thanks!
To expand on #HenrikR's answer, the generator will not wait unless it receives a promise.
export const GoogleSignIn = () => {
const GoogleAuth = window.gapi.auth2.getAuthInstance();
return new Promise((resolve, reject) => {
GoogleAuth.signIn({scope: 'profile email'})
.then(
(res) => {
const GoogleUser = GoogleAuth.currentUser.get();
resolve(GoogleUser.getAuthResponse().id_token);
},
(err) => {
reject(err);
}
);
});
};
Accordingly, you should wrap the yield statement in a try/catch. Simplified and somewhat lazy:
function *googleLogin() {
try {
const id_token = yield call(GoogleSignIn);
if (id_token) { /* Possibly with more checks and validations */
console.log(id_token);
const response = yield call(HttpHelper, 'google_token', 'POST', id_token, null);
console.log(response);
}
} catch (e) {
console.log(e);
}
}

Resources