im currently working on a project that uses a few microservices and one of them must do the same thing over and over again.
The code looks like this:
refresh: function(){
return somePromise
.then(doA)
.then(doB)
.then(doC)
.catch(error)
}
So currently another function calls this "refresh" function with setInterval every second.
The problem is that because of the async nature of these calls in refresh method, some bugs appear.
I changed the code to call the 'refresh' method again recursively in the last '.then' statement and removed the setInterval.
refresh: function(){
return somePromise
.then(doA)
.then(doB)
.then(doC)
.then(refresh)
}
Nowthe bugs appear to be gone and everything works perfectly.
My question is:
Is this a good practice? Are there any memory problems with calling the "refresh" method recursively in the last '.then' statement?
Is this a good practice?
If you just want it to repeat whenever it finishes and make sure the next iteration doesn't start before the previous one finishes, this is a perfectly fine practice (much better than setInterval()). Your looping stops if there's a rejection anywhere so you may want to code what should happen with a .catch().
Are there any memory problems with calling the "refresh" method recursively in the last '.then' statement?
No. There are not. Since .then() is always called asynchronously, the stack always gets to unwind and since you presumably have async operations in your chain, there should be time for normal garbage collection.
See Building a promise chain recursively in javascript - memory considerations for more discussion of memory consumption during the looping.
FYI, this must be pseudo-code because a function defined as a property refresh: function() {} won't be directly callable with .then(refresh). So, I'm assuming you did that properly in your real code.
Related
So I kind of understand the JS event loop, but still have a few questions. Here is my scenario and a few questions.
So let's say I have these functions:
function1 - reads an absolute huge file.
function2 - console.log("Hey");
function3 - console.log("What's up");
The way I am understanding this, and correct me if I'm wrong, what would happen is that the function1, function2, and function3, would be added to the queue. Then function1 would be added to the call stack followed by the next two functions.
Now the part where I'm confused is because the first function is going to take an extremely long time what happens to it? Does it get pushed somewhere else so that the next two functions are executed? I think the answer to this is that the only way it gets pushed somewhere else so that you can continue running is to make it an asynchronous function. And the way you make it a asynchronous function is either by using a callback function or promises. If this is the case how does it know that this is a asynchronous function? And where does it get pushed to so that the other two functions can be executed since they are relatively simple?
I think I answered the question myself but I keep confusing myself so if somebody could explain in extremely simple terms that would be great and sorry for the extremely stupid question.
Ordinary function calls are not pushed on the event queue, they're just executed synchronously.
Certain built-in functions initiate asynchronous operations. For instance, setTimeout() creates a timer that will execute the function asynchronously at a future time. fetch() starts an AJAX request, and returns a promise that will resolve when the response is received. addEventListener() creates a listener that will call the function when the specified event occurs on an element.
In all these cases, what effectively happens is that the callback function is added to the event queue when the corresponding condition is reached.
When one of these functions is called, it runs to completion. When the function returns, the event loop pulls the next item off the event queue and runs its callback, and so on.
If the event queue is empty, the event loop just idles until something is added. So when you're just starting at a simple web page, nothing may happen until you click on something that has an event listener, then its listener function will run.
In interactive applications like web pages, we try to avoid writing functions that take a long time to run to completion, because it blocks the user interface (other asynchronous actions can't interrupt it). So if you're going to read a large file, you use an API that reads it incrementally, calling an event listener for each block. That will allow other functions to run between processing of each block.
There's nothing specific that identifies asynchronous functions, it's just part of the definition of each function. You can't say that any function that has a callback argument is asynchronous, because functions like Array.forEach() are synchronous. And promises don't make something asychronous -- you can create a promise that resolves synchronously, although there's not usually a point to it (but you might do this as a stub when the caller expects a promise in the general case). The keyword async before a function definition just wraps its return value in a promise, it doesn't actually make it run asynchronously.
I think I know the answer to this but not sure. Wanting to confirm more than anything. The question applies (I think equally) to all three async approaches (callbacks, promises, async/await), but I'll ask it in the context of promises.
As I understand it, asynchronous programming is intended (at least) for event-driven applications to perform tasks in response to events, without the processes of doing those tasks blocking the ability to do any other tasks (presumably in response to other events) the application. eg. one event might trigger this series of tasks:
Query a database for some data
Wait for the response
Manipulate the data from the response (or handle errors as needed)
Write changes back to the database
done.
In more traditional programming (eg. C/C++) there'd be a main function that calls all that, and might get something back from it. But generally, the process of that main function, sitting around waiting for that to come back, blocks other operations (unless you start manually manipulating threads, or other stuff, that this JS async programming is presumably supposed to spare us from, right?).
But in the above example, supposedly, the (conceptual) "main function" doesn't need anything back from it. Step 5 isn't "return some result I need to act on", it's "done", end of story. If I understand correctly, the above is more likely called by a listener. That listener was set up by JS/node's equivalent of a "main function" -- the code that runs from the entry point of the app -- which has long since ended and the listeners are now running the show. Anything else this entire app needs to do will be triggered by some other independent event, caught by a listener. (Not that this is the only way but as I understand it this is pretty common). So perhaps the user sees the results, and hits another button or whatever to initiate some other, separate, independent, task with it. The above task is long deceased.
Ok... if all that's correct then there's this: For each of those 5 steps, we need to call them in succession. Each step relies on something provided by the one before it. So that process basically needs to be synchronous.
In promise code I believe it looks something like this:
askDbForData() // step 1
.then(responseFromDB => { // step 2
makeTheDesiredChangesToTheData(responseFromDB) // step 3
})
.then(changedData => writeBackToDB(changedData)) // step 4
Looks to me like ultimately this is chaining functions one after the other to perform what is otherwise essentially a synchronous task.
But but but... Synchronous... = blocking?
I've just realized how this doesn't appear to be very clear to me in most of the documentation/articles I've read on this. This is what I need to clear up...
I think the point is: the part where .next(...) picks up the result and sends it off to the next piece in the chain -- that part is "blocking" (though it happens in the blink of an eye so it's kinda moot), but each of those (presumably time consuming) functions (like askDbForData()) -- which are supposed to be asynchronous, and return promises -- do their thing separately and independently of any other control flow, etc, thus not blocking anything.
In other words, the promise chain itself is synchronous, but each piece along the way is asynchronous. The kicker, I think: Not asynchronous to other tasks in the same chain, but asynchronous to everything else the app is doing in other chains initiated by other events.
It might be that anyone reading this will read it and go "yeah well duh, that's the whole point". Perhaps that's what I'm hoping. But if it is, it hasn't been clear in any of my research so far, so it's be great to get it clear from someone(s) who "get" it. I think if all this IS correct, then it pretty much clears up nearly every other confusion I've had with this topic.
So... Yes this is long, but it is only one question. The question is:
Is that it -- is that the point -- or if not, what am I missing?
Thanks!
Looks to me like ultimately this is chaining functions one after the other to perform what is otherwise essentially a synchronous task
No, the code you show there only performs the synchronous part of askDbForData(), then returns. If properly coded, this first part is usually nothing.
I think the point is: the part where .next(...) picks up the result and sends it off to the next piece in the chain -- that part is "blocking" (though it happens in the blink of an eye so it's kinda moot)
Again no, the continuations are only called once the previous step is done. Once a continuation happens, the same split happens, first the synchronous (and hopefully minimal or non-existent) part runs then the rest of the function is registered as a continuation.
In other words, the promise chain itself is synchronous, but each piece along the way is asynchronous.
Absolutely not, the chain of promises is asynchronous. .next() stores a function reference to be called at a later date, it neither calls nor waits for the call of that function code.
The kicker, I think: Not asynchronous to other tasks in the same chain, but asynchronous to everything else the app is doing in other chains initiated by other events.
I've tried to avoid the word "chain" because it seems it's confusing you even more. It's not a chain, it's a tree, you can have promises executed in parallel or sequentially. So again, no.
Consider this.
You have a function A that returns a promise..a promise for something to come.
You also have a function B that does something else.
FunctionA().then(result=>{console.log(result)}).catch();
FunctionB();
If the promise in function A takes a long time to resolve..why not go ahead and do FunctionB while we wait?
Get it?
Here is a picture of my web execution captured by Chrome Performance Devtools:
I notice that functions will be stopped many times during execution, when my web functions are stopped Chrome executes some RegExp operations (as shown in the picture). I don't understand what this is, and why it happens. Please help explain, thanks.
Update: here is a function which is also executed in the same manner:
What you describe
The way you describe the problem it sounds like you think the JavaScript virtual machine is putting the functions on hold (stopping them) while they are executing (i.e. before they return) to do something else and then resumes the functions.
The image you are showing does not suggest that at all to me.
What I'm seeing
The VM executes:
callback, which calls
some function whose name is hidden by a tooltip, which calls:
fireWith, which calls:
fire, which calls:
etc...
Then the deepest function returns, and the one that called it returns, and so on and so forth until fire returns, fireWith returns, the function whose name we cannot read returns, and callback returns.
Then the VM runs a RegExp function, and it calls a function named callback again, and the whole thing starts anew. In other words, the second column with callback and the rest is a new invocation of the functions. The functions are not "stop[ping] for a little time": they are called multiple times.
I see this all the time in libraries that respond to events. They typically will loop over event handlers to call them. Given a complex enough library, there'a fair amount of glue code that may sit between the loop that calls the handlers and your custom code so there's a lot of repetitive calls that show up in profiling.
For a couple of years, I was dealing with a part time problem where some DOM elements loaded with jquery html function were not accessible immediately after the function call (The behaviour was a bit like executing a function without waiting for the document ready event). Even though .html() is suppose to be synchronous, this SO answer (and also this one) suggests using the promise of the html function:
$('#divId').html("<h1>hello</h1>").promise().done(function(){
//Callback
});
A promise could make sense in such context but what intrigues me about this promise is that it will also be returned with every jquery's object:
$('#divId').promise().done(function(){
//Will also be called...
});
Since I couldn't find anything about it in the documentation of the html function, I was wondering what was the real purpose of this promise and if it is used correctly in this context.
The two methods are not related. The reason people often suggest this is because someone found out that they could use .promise().done() to make their code that has a race condition work. It worked for the same reason wrapping the same code in setTimeout(fn, 0) would make it work; it pushes it off to the callback queue to be ran later, likely after the browser performs a render or after some other async callback completes.
.html is synchronous, does not have a callback, and does not need a callback. However, the browser's renderer is asynchronous, so it won't render the change until after the callstack is clear. Using .promise pushes the callback off to the callback queue, thus running the code after a render which resolves the race condition or async logic flaw.
.promise() used on a jquery collection returns a promise that will resolve once all currently running jquery animations are complete. If there are no currently running animations, the promise will resolve immediately and the callback will be pushed to the callback queue to be called once the stack is clear.
It's nothing more than a bandaid. I'd suggest not using it, and instead fixing whatever async logic flaw is causing it to be the solution.
Set UP:
Hi. I am trying to learn about creating/instantiating objects. I was thinking I should be able to create multiple objects that may have different amounts of similar works (like gather news articles) and would "report completion" regardless of the order created. So far I am not clear on this, so here is a basic example followed by the stated question:
function test(count){
this.count = count;
for(var i = 0; i< count; i++){}
console.log(i);
}
new test(1000);
new test(10);
Actual Question:
Based on the code above, I would expect the second instance to print first, but it does not. What would be the correct way to set this up so that which ever object finishes its work would print first?
* Modify my question *
Sorry...what I am really intending to ask is how to set objects to have more of an asynchronous behavior. I am new to Stack, so please let me know if I should close/move this question.
In general JavaScript is uses a synchronous execution model, the event queue. All calls are placed here, basically in the order they appear in your source code (respecting the scope they are in).
So if you start some function, nothing else is executed until that very function is finished. In your case you place both calls on the event queue, but the second call will only be executed, when the first one has finished.
There, however, exceptions: Worker or AJAX requests.
Here the execution is outside the usual event queue and you use message handlers or callbacks to use the results, after the execution is finished. In most cases, however, you can't be sure in which order the calls are finished as there are many circumstances affecting the ordering of execution (network delay, cpu usage, etc.)
In your case, it seems, you want to load external resources, anyway. So have a look at how AJAX works.
You're not creating different parallel execution threads : the first test(1000) is wholly executed before the following line even starts.
In Javascript, when you're not using webworkers (which you should probably not use), all your code is always executed in a single thread. This thread is awaken by the browser on events and goes back to sleep when the function called by the browser returns.
Note that even with threads, even in naturally parallel languages, you hardly would have had any guarantee regarding what loop ends first.
The reason why the second instance does not print first is that the first call new test(1000) runs to completion before the next line new test(10) starts executing.
If you want the second call to run first, swap the two lines...
Edit:
By the way, any decent compiler will remove this line completely:
for(var i = 0; i< count; i++){}
So you can't even expect the first call to take more time than the second...
The second instance gets instantiated only after first object is instantiated.
So it first prints 1000 after it comes to new test(10)
Because it is single threaded program