I'm having some trouble on understanding the unsubscribe() function usage for detaching listeners.
I'd like detach listener every time that user click button show table for changing view options.
Actually this is my code.
Previously query was called unsubscribe as reported in the official Firestore documentation (I also tested the same example code from documentation in my project) and in console log always return unsubscribe is not a function
let query;
$(".btnShowTable").on("click", function () {
if(typeof query != "undefined") query.unsubscribe();
createTable(param);
});
function createTable(param) {
query = db.collection("test1/test2/"+param).orderBy("dataora", "desc").limit(10);
query.onSnapshot(function (querySnapshot) {
querySnapshot.docChanges().forEach(function (change) {
// get datas
});
});
}
What should I change in my code?
query is a Query type object, and you can see from the API documentation that it doesn't have an unsubscribe() function. What you'll need to do is follow the instructions in the documentation. It says that onSnapshot() returns an unsubscribe function to call when it's time to unsubscribe.
// subscribe to query results
const unsubscribe = query.onSnapshot(...)
// later, unsubscribe the listener
unsubscribe()
Related
i have the following code with Pusher:
Echo.private("channel").listen(".foobar", (e) => {
this.fetchData();
});
When there is an incoming request, I want data to be fetched again. But not on every Pusher event. I want the data to be fetched only once in 5 seconds.
I was thinking about a interval that is reset when there is a new incoming event, but how to achieve this?
Ok, first of all it's a Laravel Echo code. It may be using pusher behind the scenes, but saying it's a pusher code is slightly incorrect.
Then, if I understand you right, you need some kind of debounce function. For example lodash offers one.
const debouncedFunction = _.debounce(() => {
this.fetchData()
}, 5000);
Echo.private('channel').listen('.foobar', e => {
debounced()
})
debounce will create debounced version of function which you can then call, or even cancel, because it comes with cancel method.
debouncedFunction.cancel()
I am using fire store with angular and used onsnapshot method. To remove the listener I did the similar way what docs is suggesting but still I am receiving the real time updates. Any suggestions?
unsubscribe:any;
this.unsubscribe = db.collection("cities")
.onSnapshot(function (){
// Respond to data
});
this.unsubscribe();
I'm using mobx-state-tree's onSnapshot() feature to listen to state changes, I then persist the state with every change in local storage. This is how I do it:
import { onSnapshot } from "mobx-state-tree";
onSnapshot(store, newSnapshot => {
saveLocalSnapshot(newSnapshot);
});
My question is, how do I unsubscribe from onSnapshot() when my app needs to stop persisting every snapshot?
Helper functions like onSpanshot or onPatch (and basically every other subscribe method) return IDisposer, which is basically a function that you can call to literally dispose the subscription.
I try to get all 10 records using this:
exports.checkchanges = functions.database.ref('school/{class}').onCreate(snap => {
const class=snap.params.class;
var ref = admin.database().ref('/students')
return ref.orderByChild(class).startAt('-').on("child_added", function(snapshot) {
const age=snapshot.child("age");
// do the thing
})
)}
The problem is that after I get the 10 records I need correctly, even after few days when a new record is added meeting those terms, this function is still invoked.
When I change on("child_added to once("child_added I get only 1 record instead of 10. And when I change on("child_added to on("value I get null on this:
const age=snapshot.child("age");
So how can I prevent the function from being invoked for future changes?
When you implement database interactions in Cloud Functions, it is important to have a deterministic end condition. Otherwise the Cloud Functions environment doesn't know when your code is done, and it may either kill it too soon, or keep it running (and thus billing you) longer than is necessary.
The problem with your code is that you attach a listener with on and then never remove it. In addition (since on() doesn't return a promise), Cloud Functions doesn't know that you're done. The result is that your on() listener may live indefinitely.
That's why in most Cloud Functions that use the Realtime Database, you'll see them using once(). To get all children with a once(), we'll listen for the value event:
exports.checkchanges = functions.database.ref('school/{class}').onCreate(snap => {
const class=snap.params.class;
var ref = admin.database().ref('/students')
return ref.orderByChild(class).startAt('-').limitToFirst(10).once("value", function(snapshot) {
snapshot.forEach(function(child) {
const age=child.child("age");
// do the thing
});
})
)}
I added a limitToFirst(10), since you indicated that you only need 10 children.
I would like to use the once method to retrieve data from a Firebase ref, but am not receiving any data in the snapshot.
Here is the simple data retrieval:
EDIT After further inspection, I found that a transaction was being scheduled shortly after the once value listener. (For simplicity I will place the transaction directly after the listener for this code example.)
dataRef.once('value', function (snapshot) {
snapshot.val(); // returns `null`
});
dataRef.transaction(function (currentValue) {
if (currentValue) {
// make changes
}
return currentValue;
});
There is data at this firebase ref. To verify, I tried using on instead of once. In this case, the callback is invoked twice:
dataRef.on('value', function (snapshot) {
snapshot.val(); // returns `null` first, then called again and returns correct value
});
What is causing this behavior? I would expect the snapshot to have the correct value the first time the callback is invoked. Otherwise, the once method has no useful purpose.
In the Firebase docs for transaction there is a third argument applyLocally.
By default, events are raised each time the transaction update function runs. So if it is run multiple times, you may see intermediate states. You can set this to false to suppress these intermediate states and instead wait until the transaction has completed before events are raised.
Because of this default value, the once value listener is firing after the transaction runs locally the first time, even though no data has been retrieved from the server (passing null as the transaction's currentValue). By passing false as the applyLocally parameter, this local event is suppressed, and the once callback will only be invoked after data has been retrieved from the server:
dataRef.transaction(function (currentValue) {
if (currentValue) {
// make changes
}
return currentValue;
},
function(){},
false);