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.
Related
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));
I have two intervals that need access to the same data.
So in one interval I want to push() an element to an array and then in the other interval I want to get the first element from the array and then remove it.
for example:
let array = [];
let count = 0;
setInterval( () => {
array.push(count);
count++;
}, 1000);
setInterval( () => {
let data = array[0];
array.shift();
console.log("received data: "+data);
}, 1000);
the output of this is:
received data: 0
received data: 1
received data: 2
received data: 3
....
Does this also work with more complex functions and bigger arrays?
Could this cause any weird behaviour? Maybe it could shift and push at the same time and mess up the array?
Is this a good way to do that? Are there better ways?
EDIT:
The reason i want to do this. Is because I want to download data from many different links. So inside my script i call a download(link) function, but this will result in the script trying to download a lot of links at the same time. So i want to create a buffer, so that the script only downloads from 100 links at the same time.
Inside the script i want to call download(link) wherever i want and then let an interval take care of downloading only 100 links at the same time. So it removes 100 links from a buffer and downloads them. While the script pushes new links to the same array.
My main concern is that while i am doing a shift() the array will reorganize itself somehow. Might js try to make a push() in between this reorganization phase? Or will js not do any array operations on the array until shift() is completed?
Your general idea of pushing links to an array asynchronously and then removing them from the array in a separate asynchronous task is fine, it'll work.
My main concern is that while i am doing a shift() the array will reorganize itself somehow. Might js try to make a push() in between this reorganization phase? Or will js not do any array operations on the array until shift() is completed?
Javascript is single-threaded, so this isn't something to worry about - if one interval triggers a function that does stuff, that function's synchronous actions (like manipulating an array) will run to the end before any other interval callbacks can run.
The issue of shared mutable state is a problem for many other languages, but not for Javascript, at least in most cases.
I have application on Node.js with using Express as API route and MongoDB as DB.
I have a raffle. User must join raffle only one time.
I am currently using an array in memory with participating, but if you will make two request to API at the same time, user will be joined in raffle two times.
How can i disallow to join raffle more than one time?
You would need to structure your workflow to support idempotent operation. That is, performing the same operation twice does not change the result.
For example, incrementing a variable is not idempotent, since calling the increment function twice resulted in the variable get incremented twice (e.g. calling x++ twice will result in adding 2 to x). I think this is the essence of your current design, where you mentioned: " if you will make two request to API at the same time, user will be joined in raffle two times".
An example of an idempotent operation is setting a variable to a value. For example, calling var x = 1 multiple times will only result in value 1 getting assigned to x. No matter how many times you call that line, x will always be 1.
Some resources to help get you started:
What is Idempotency
Database operation that can be applied repeatedly and produce the same results
What is an idempotent function
How to Write Resilient MongoDB Applications
You should maybe store the array in mondodb, you don't want to loose this list if node restart.
About the "join two time" problem, just throttle the client side function that make the request to your API, so that it can only be called one time during the time passed in your throttle function.
Exemple throttle function :
function throttle (callback, limit) {
var wait = false;
return function () {
if (!wait) {
callback.apply(this, arguments);
wait = true;
setTimeout(function () {
wait = false;
}, limit);
}
}
}
and now your request function :
var throttleApiFunc = throttle(apiFunc, 5000);
// this can only trigger one time each 5 seconds
throttleApiFunc();
Can anybody explain in plain English what RxJS Observable debounce function does?
I imagine it emits an event once in a while depending on the parameters, but my code below doesn't work as I expected.
var x$ = Rx.Observable.fromEvent(window, 'click')
.map(function(e) {return {x:e.x, y:e.y};})
.debounce(1000)
.subscribe(function(el) {
console.log(el);
});
and the JsBin version.
I expected that this code would print one click once per second, no matter how fast I am clicking. Instead it prints the click at what I think are random intervals.
Debounce will emit a value after a specified time interval has passed without another value being emitted.
Using simple diagrams the following may provide greater help:
Stream 1 | ---1-------2-3-4-5---------6----
after debounce, the emitted stream looks like as follows:
Stream 2 | ------1-------------5---------6-
The intermediate items (in this case, 2,3,4) are ignored.
An example is illustrated below:
var Rx = require('rx-node');
var source = Rx.fromStream(process.stdin).debounce(500);
var subscription = source.subscribe(
function (x) {
console.log('Next: %s', x);
}
);
I used node to illustrate this... assuming you have node installed, you can run it by typing
$node myfile.js (where the aforementioned code is in myfile.js)
Once this node program is started you can type values at the console -- if you type quickly items are ignored, and if type intermittently fast and slow items will appear after a gap in typing (in the example above I have 500ms) at the console ("Next: ")
There is also some excellent reference material at https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/debounce.md
Long story short:
debounce waits for X time that the stream isn't emitting any new value, then let the latest value pass.
Long story:
Once a value is emitted, debounce will pause its emission for X time to see if another value is emitted, in fact blocking the stream during this time. If a new value is emitted during the debounce time then the timer is restarted and debounce waits again for the full time.
If its timer expires without any new value being emitted, it let the latest value pass.
Let's say that you want to add autocomplete to an input box. If the user insert "a" you may want to show him the choices "acorn, alaska", but if the user right after press "l" you would propose just "alaska". In this case it's better to wait for the user to stop pressing the keyboards to avoid doing unnecessary work. debounce it's the right tool here: it waits for X time the the stream isn't emitting any new value
.debounce() produces the last received value if no values were received within the specified interval.
It means that as soon as you click within a second - nothing will be produced.
If you want to throttle values to be emitted no more frequent than every second you need to use .sample(1000) instead.
I might just be being a bit dim here, or it might be my relative weakness with javascript, but I'm kinda stuck.
I have a justgage dial, showing number of people checked in an office, out of a total number.
I have a setInterval call just after the gauge is initiallised. But I want to update BOTH the number present, AND the total number, because both might potentially change. I can get the numbers via an ajax call to my own api - but because the ajax call is asynchronous, if I use
setInterval (g.refresh(myfunc()), 1000)
how do I get multiple returns out of myfunc.
Alternatively, if I do
setInterval( myfunc(g), 1000)
function myfunc(g){
var foo=g;
$.ajax(blah)
.done(function(json){
// no g here
})
I have no reference to g on successful ajax call. (Though it is visible at var foo=g)
How do I get around this (multiple returns, or visible object)
Maybe there is a better solution but try to create the foo var as global and then you can use this in all the places you want.