d3.timer update dispatches multiple times - javascript

I've changed an slider to parse JSON data with an start and end date to create a d3.js playback visualization.
My REPL:
https://svelte.dev/repl/69ede1e0f5a74f0c81a1213ce844b9f1 ( slider.svelte -> line 145 function: update() )
What happens is that once a value is rounded to a hour, it dispatches it. but 6-7 values round to the hour so it gets dispatched 6-7 times.
Is there a way to return the function if the hour was already dispatched?
I'm using Svelte
Regards,
Pepijn

You should be able store the already dispatched hours in an array or object and check that one before firing or handling the event. It is rather hard to show with your example because there are a lot of other things going on. If you can simplify it to the pure basics it would be easier.

I solved my problem by adding a variable named "lastDispatch", I set this to the startDate value.
in my update function I wrapped the dispatch function in this check:
if(lastDispatch.getHours() < roundMinutes(new Date(target)).getHours())
and before dispatching I overwrite the variable again
lastDispatch = roundMinutes(new Date(target));

Related

Make AlpineJS recognize changes to objects

I'm using AlpineJS and momentjs. The user can add a bunch of datetimes and those get pushed to an array. This array is rendered to the page with an x-for.
Now I want a method setTime, that changes the time of every datetime object. In theory this is pretty easy. But I figured, that AlpineJS will not catch, that something has changed and therefore not re-render the x-for.
I'm using this.dates.map(item => item.hour(10).minute(0)); in my example here: https://jsfiddle.net/suny1vj9/
Is there a way to tell AlpineJS to rerender, since I know when this needs to be rerendered?
I also thought about having the data twice. One as moment/Date object, and one as the string representation. That solves the problem too, but I feel like there has to be a prettier solution than maintaining two similar arrays and keeping them in sync.
How would you solve this problem differently?
It's a known issue with MomentJS mutability. And since any change in the object replaces the original object, Alpine.js cannot detect the change. To fix it, you will have to clone() the original object after setting the hour and minutes, so that Alpine.js can detect that the object has been changed (I mean it's a new object that time)
Also, the map() function returns the new Array, so you need to change your code like this.
function test() {
return {
dates: [
moment("2022-04-23"),
moment("2022-04-25"),
moment("2022-04-26"),
moment("2022-04-27"),
moment("2022-04-28")],
setTime() {
this.dates = this.dates.map((item) => item.hour(10).minute(0).clone())
},
}
}
This will solve your problem :)
Here is the fiddle link https://jsfiddle.net/tujfyhs2/1/

【Excel.Worksheet.onChanged】I only changed the range value once, but the callback was run many times. Why is that?

I want to implement a feature,Listen for changes in one range and assign values to another range.
My implementation steps:
1.Use the onChanged event to listen for changes to the data.
2.Assign the changed value【event.details.valueAfter】 to the target range in the callback function.
This is my code:
https://i.stack.imgur.com/lealz.png
But the console will show that it ran the callback many times,This is the console log:
https://i.stack.imgur.com/SS941.png
Is there something wrong with my code?Is there a good solution?

Rx.Js: understanding expand operator

I post data to backend, processing data takes some time and long polling is not a solution in my particular case, so I send request each 5 seconds with expand operator
this.apiService.postData(data).pipe(
expand((status) =>
status.comptete? this.apiService.askStatus(status.request_id).pipe(delay(5000)) : empty()
),
map((result) => {
// processing result here
})
);
The question is how can I make delay be dynamic (e.g. at first time I want to ask for status in 1 second, at second time in 2 seconds and so on)? And two more questions. Have I understood correctly that if I add take(N) operator that will limit askStatus calls to N? Have I understood correctly that I don't need to do any sort of unsubscription here?
expand() passes also index every time it calls the project function so you can calculate delay based on that:
expand((status, index) =>
status.comptete ? this.apiService.askStatus(...).pipe(delay(...)) : empty()
Using take(N) inside expand() won't help because expand() calls the project function on every emission from both source and inner Observables. But you can of course use take(N) after expand().
You don't have to unsubscribe from askStatus() manually if you handle unsubscription later where you also subscribe.

react child calling parent function is slow

I've tried to keep this as brief as possible, but with enough detail.
I have a yearly calendar which I need to be interactive so that when you click on a date and drag the mouse across to another date, all dates within the current dragged range have their class changed dynamically in a temporary state. An onMouseUp event would then make the temp changes permanent.
The calendar is broken down in to class objects so that:
<Year>
<Month>
<Day>
<Shift {some state values from Year need to be passed here}/>
</Day>
</Month>
</Year>
<Year> contains some functions that changes some states in the constructor for <Year> - namely a start and end date. This function is passed all the way to <Shift> so that when there's an onMouseDown event a the <Shift> level it calls the function in <Year> that sets the start date.
Additionally hovering sets an end date using the same process, so clicking one then dragging across many <Shift /> components will set a start and end date at the <Year> level. When the user is happy with their selection, an onMouseUp event would commit these changes to a permanent display.
This start and end date was intended to be used in each <Shift /> component to determine the CSS class used for rendering for that <Shift>.
Turns out that simply calling the date setting functions slows the whole thing down dramatically and there's massive lag in the drag event, even when I modify the code so that the start and end dates literally do nothing except be stored in <Year>.
It's like I'm re-rendering the whole <Year> component unnecessarily, meaning all others get re-rendered too, but since the start and end dates aren't even being passed anywhere, I don't see how?
Any help on restructuring the work flow would be appreciated.
It sounds like you're constantly updating the state as you're hovering. To avoid that use a debouncer so you only update the state at the end of the hover:
// Shift component
debounceSetEnd(date) {
clearTimeout(this.timer);
this.timer = setTimeout(() => this.props.setEnd(date), 1000);
}
onMouseEnter={() => this.debounceSetEnd(this.props.date)}
The solution was to use PureComopnents instead of Components (or alternatively make use of componentShouldUpdate() with clearly defined logic) and use immuatableJS to ensure I used proper immutable objects... which I clearly had not (shame on me!)

How can I know when a Firebase query has ended

I want to collect the most recent 10 items from my datastore. I believe I am supposed to do this using .child() and .limitToLast(), which emits an event every time a result has been added to the child.
I don't necessarily know if there are 10 items in total, so a simple counter won't work.
How do I know when Firebase is finished giving me results?
Example lookup code:
var plots = [];
firebaseDatastore.child("plots").orderByChild("unicode-timestamp").limitToLast(10).on("child_added", function(snapshot) {
// Add the new item to the list
plots.push(snapshot.val());
});
I need to know when the final plot has been added, regardless of whether it has hit the limit.
A Firebase query never really ends. It continues to monitor (in your case) the plots by unicode-timestamp and keep a "window" of the last 10 plots.
So:
child_added:timestamp1
child_added:timestamp2
...
child_added:timestamp9
child_added:timestamp10
And then when you add another plot:
child_removed:timestamp1
child_added:timestamp11
If you are not looking to use this behavior, you have two options:
use a value event and then snapshot.forEach over the child nodes
keep a counter and off your listener when you've reached the number of children you expect

Categories