How to ignore vscode events from firing within a certain time interval? - api

For example, if I trigger onDidChangeTextDocument events consecutively, with an interval of at maximum 1 second, then I would like to avoid this event's associated logic.
However, if 1 second has passed since the lastest onDidChangeTextDocument has been triggered, I would like for it to proceed with its logic.

This approach is known as "coalescing events". A typical approach is to start a timer when an event appears with the required interval. Every new event restarts the timer, so it never triggers unless there are no new events within the timer value. The triggered timer then calls any further code, handling the coalesced events. This might cause some problems if you have to process all data sent by each event. In that case you have to collect that data on each invocation of your event handler.
Here's code to handle changes per file in a VS Code extension:
private changeTimers = new Map<string, ReturnType<typeof setTimeout>>(); // Keyed by file name.
workspace.onDidChangeTextDocument((event: TextDocumentChangeEvent) => {
if (event.contentChanges.length > 0) {
const fileName = event.document.fileName;
const timer = this.changeTimers.get(fileName);
if (timer) {
clearTimeout(timer);
}
this.changeTimers.set(fileName, setTimeout(() => {
this.changeTimers.delete(fileName);
... your processing here
}, 1000));
}
});

Related

Expo Calendar Creating and Tracking Events

I am having a seriously tough time figuring out how to effectively manage events created with .createEventAsync() method in expo-calendar API. Docs found here. This is the structure of the parameter I am entering into .createEventAsync().
testEvent = {
calendarId: calendarId,
title: event.position,
startDate: shiftStart,
endDate: shiftEnd,
location: event.store.name,
alarms: [],
id: event.id,
}
The idea is to have the event id on the app calendar be the same as the id on the OS calendar, but it seems like that is not possible. I am trying to build a system that requests permissions, if permissions granted then sync all events on the app with the os calendar. If the event already exists, do not create another event.
The function runs a check with:
async function checkEventExists(eventId: any) {
try {
const event = await Calendar.getEventAsync(eventId)
console.log(console.log(event))
if (event) {
return true
}
} catch {
return false
}
}
If false, event is not created. If true then .createEventAsync() is called.
Currently, new instances of the same event are created every time the app polls data from the server and this is unrelated, but also creates 7 instances of 1 event each time data is polled. How do people usually manage and track calendar events after creation? I thought event id would be a good way to tell if the event is one and the same, but I was wrong.

How to subscribe and unsubscribe from EventStream on the first event received?

I am trying to figure it out if there is a function in the Bacon.js API that allows to subscribe to an EventStream and when the first event fires up, the handle is unsubscribed. The way to do it that I know is the following:
let stream = new Bacon.Bus();
stream.onValue(val => {
doSomething(val);
return Bacon.noMore;
});
But is there something like stream.onValueOnce that automatically unsubscribe the handler after it is executed?
I also know that there is the Bacon.once that creates a EventStream that returns a single value and then ends the stream but this is not what I am looking for.
Update
As Bless Yahu sais, take or first methods can be used. To be more specific, you have to call it from the created eventStream like that:
let stream = new Bacon.Bus();
stream.first().onValue(val => {
doSomething(val);
});
Here is a fiddle that shows it:
https://fiddle.jshell.net/3kjtwcwy/
How about stream.take(1)? https://baconjs.github.io/api.html#observable-take
Or stream.first()? https://baconjs.github.io/api.html#observable-first

redux-observable return multiple action types

I am using redux-observable and this is what I am trying to do.
When an actiontype of 'APPLY_SHOPPING_LIST' comes in dispatch 'APPLYING_SHOPPING_LIST' and after 5 seconds dispatch 'APPLIED_SHOPPING_LIST'. This is the code that I have come up with so far
const applyingShoppingListSource = action$.ofType('APPLY_SHOPPING_LISTS').mapTo({ type: 'APPLYING_SHOPPING_LISTS' });
const applyingShoppingListSourceOther = action$.ofType('APPLY_SHOPPING_LISTS').mapTo({ type: 'APPLIED_SHOPPING_LISTS' }).delay(5000);
const concatList = applyingShoppingListSource.concat(applyingShoppingListSourceOther);
return concatList;
Now the problem is that only 'APPLYING_SHOPPING_LISTS' gets fired, the 'APPLIED_SHOPPING_LISTS' does not get fired to the reducer at all. Am I missing something here?
Just to add to this, when I used flatMap it worked, given below is the code
return action$.ofType('APPLY_SHOPPING_LISTS')
.flatMap(() => Observable.concat(Observable.of({ type: 'APPLYING_SHOPPING_LISTS' }), Observable.of({ type: 'APPLYING_SHOPPING_LISTS' });
I am confused how this works and the other does not?
There's a couple issues. Since Observables are lazy, your second action$.ofType('APPLY_SHOPPING_LISTS') for applyingShoppingListSourceOther is being concat'd after the first applyingShoppingListSource, so it won't be listening for APPLY_SHOPPING_LISTS until after the first one is has completed, but it will never realistically complete because you're taking all actions that match, forever.
Said another way, your code does this:
Start listening for APPLY_SHOPPING_LISTS and when received map it to APPLYING_SHOPPING_LISTS
When that first Observable completes (it never does) start listening for APPLY_SHOPPING_LISTS again, this time when received map it to APPLIED_SHOPPING_LISTS but wait 5000 ms before emitting it.
You could solve the particular issue of the first not ever completing by using .take(1) or .first() (same thing), but you usually need to write your epics to not ever stop listening so they respond to actions at any time.
I think what you want is this:
const exampleEpic = action$ =>
action$.ofType('APPLY_SHOPPING_LISTS')
.mergeMap(() =>
Observable.of({ type: 'APPLYING_SHOPPING_LISTS' })
.concat(
Observable.of({ type: 'APPLIED_SHOPPING_LISTS' })
.delay(5000)
)
);
I used mergeMap but you may want to use switchMap to cancel any previously pending APPLIED_SHOPPING_LISTS that haven't emitted yet. Your call.

How to cancel all grid store XHR requests but the last [dojo dgrid]?

I am using dojo dgrid 0.3.14
I have live search toolbar
On every user input change i do
searchGrid.set("store", searchStore, query);
It works fine but back end returns data in no order.
So sometimes grid is being refreshed with slow previous response.
How to cancel all grid store XHR requests but the last?
current solution for DGrid is
_abortQuery: function () {
// console.log("_abortQuery" , this._refreshDeferred);
if (this._refreshDeferred && this._refreshDeferred.cancel){
this._refreshDeferred.cancel();
}
return this;
},
refresh: function () {
this._abortQuery();
return this.inherited(arguments);
},
If you're responding to user input on every keypress, I would suggest that rather than seeking to cancel requests, you instead debounce the input. dgrid has a utility function named debounce in dgrid/util/misc for this purpose. Debouncing refers to the practice of listening to an event, but only responding once the event has stopped firing for a certain period of time.
See https://github.com/SitePen/dgrid/wiki/misc for more information.

cy.on('select') callback only once

I have a createTable function that receives a collection of nodes (or an array of nodes), then I am able to draw a table.
I am switching to cytoscape.js now, and I really don't know how to have a listener to my select event properly.
Doing this:
cy.on('select', 'node', function(event){
window["selectedNodes"] = cy.$('node:selected');
});
I do have all information I need to draw my table, but I cannot call my createTable function inside it because it will call my function several times (once per node selected).
I've already tried to use cy.on and cy.once, but without success.
Here is my question:
How can I have a listener to my selection event, get ALL selected nodes and call (only once) my createTable function ?
I can also obtain all selected node using this:
cy.elements('node:selected', console.log("my CallBack function"));
But as it is outside an event listener (select / click) it doesn't work as I need.
Please, any help is appreciated.
Thank you.
Debounce your callback so if multiple events come in one after another, then they are effectively batched:
var timeout;
cy.on('select', 'node', function(event){
clearTimeout( timeout );
timeout = setTimeout(function(){
window["selectedNodes"] = cy.$('node:selected');
// and so on...
}, 100); // may have to adjust this val
});