I am new to react and I am stuck in this. I am calling functions in a function like so:
submit = () => {
this.props.getValue();
this.props.resetValidation();
this.notify();
this.props.toggle();
this.props.disable();
this.props.actionCost();
//this.props.action();
// this.props.actionTable();
};
What is happening is that all the functions are running simultaneously without a function getting fully executed. Why is this happening shouldnt a function be called only after first function runs successfully?
Also how do I run the functions one after the other after a function is fully executed?
Please help
The only way to stop the execution flow, is by using async/await or a generoator function, and even these are only "syntactic sugar" on top of Promise.
You are probably calling an asynchronous function, and expecting it to "complete" without using await.
Another situation is calling a function that internally using asynchronous calls (Like axios or fetch), and reply back with callbacks. In this situation the execution continues, and the callback will be called later, that's way we call them "callback"
For example:
console.log('before');
setTimeout(() => console.log('timer completed'), 1000);
console.log('after');
Will result in:
before
after
timer completed
In this example I'm logging before, then setting a timeout where I'm providing a callback (a simple function) that will be executed later (1 sec.), meanwhile the execution flow continues, and logs after. once the timer reached the system will execute my callback.
In case that you want to execute the after after the timer completed, you will have to provide a callback that will be called after the execution is done.
like this:
function logTimer(doAfter) {
setTimeout(() => {
console.log('timer completed');
doAfter();
}, 1000);
}
console.log('before');
logTimer(() => console.log('after'));
Related
how can async/await be used when calling APIs where the data you're fetching is dependent on the rest of the function content under it?
What if the fake API calls here pushed more names to the array? The updateNames function would be called already before the api calls would be done. Wouldn't I want to block the runtime in this case and make it synchronous?
let names = [];
async foo() {
await Promise.all[
this.callAPI1();
this.callAPI2();
]
this.updateNames(names);
}
In your example, this.updateNames will be executed after your API calls are resolved because you have the await keyword and it is the same as doing:
Promise.all([call1(), call2()]).then(() => { this.updateNames() })
If you have any doubt you can always try by simulating an API call with a promisified setTimeout and some console.log:
const simulateAsync = () => {
return new Promise(resolve => {
setTimeout(() => {
console.log("resolved");
resolve();
}, 100);
});
};
async function test() {
await Promise.all([simulateAsync(), simulateAsync()]);
console.log("after");
}
test();
What if the fake API calls here pushed more names to the array? The updateNames function would be called already before the api calls would be done.
updateNames would not be called until both of the callAPI# functions completed; the await makes the code block (yielding control back to the event loop) until both promises (explicitly created or implicit when the functions are async themselves) complete.
If the functions in question don't return promises, executing synchronously/eagerly, then the await Promise.all([...]) is pointless (there were no promises involved), but there's still no risk of updateNames being called before the callAPI# calls finish; either:
callAPI# returns a promise (in which case await blocks the current task until they complete, returning control to the event loop while it waits), or
callAPI# does not return a promise and all the work is done immediately
and in either case, you can't get to updateNames before they finish.
Wouldn't I want to block the runtime in this case and make it synchronous?
You are blocking the current function call/task with the await. Other tasks scheduled on the event loop can run while the await is still blocked though, and that's the advantage to async processing. Every apparently asynchronous thing in JavaScript is sharing that event loop, and if you completely blocked (rather than awaiting an async call), none of them could run. This means, for example:
setTimeout/setInterval calls don't fire
UI drawing operations don't occur
User input is blocked
All events and observer handling code is deferred
Truly synchronous calls would make all of that (and more) wait until the entirety of foo completed. This is why async code is sometimes referred to as "cooperative multitasking"; control is never wrested away from the current task without its consent like you'd see in multithreaded code, instead control is handed back to the event loop voluntarily (via await) whenever a task is blocked waiting on asynchronous processing, or when the task completes. When the async task has a result, it waits for the event loop to hand control back to it, then continues where it left off.
Loop inside of the promise works like sync code, for example:
console.log('im working')
function proLoop(){
return Promise((resolve ,rejects)=>{
for (let i = 0; i < 1000000000000; i++) {}
console.log('loop is done')
})
}
proLoop();
console.log('im working')
So even if we write is like promise it will get more time and freezes our code In other words it will works synchronically.
i find a solution but why it works?
so the solution is just warp your code as like resolved promise
like this
return new Promise.resolve().then( ()=>{
for (let i = 0; i < 1000000000000; i++) {}
console.log('loop is done')
})
but why and how???
Couple of things you need to understand here:
Promises don't make something asynchronous - they are a notification mechanism for something that's already asynchronous. Promises notify you of the success or failure of an operation that's already asynchronous.
Callback function of the promise constructor is called synchronously; it is called synchronously to start an operation that's already asynchronous.
In your case, promise constructor contains synchronous code; this is why it blocks other code.
Moving the loop inside the callback function of then executes the loop asynchronously because the callback function of then is invoked asynchronously.
Note: Even though the callback function of then method is invoked asynchronously, once it starts executing, no other code will execute until the synchronous code inside the callback is executed completely.
In both cases, the for loop will block the main event loop. The difference is when the for loop starts.
In the first case, the function passed to new Promise is executed immediately. It therefore blocks the rest of the function that creates it.
In the second case, the function passed to then() is queued up to run next time the event loop is free. The function that created it therefore finishes first and then the for loop runs. (If that's the goal, then its a pretty unintuitive approach, and using setImmediate (in browsers) or Node's process.nextTick() would be neater.)
If you wanted to shunt the work done by the for loop off the main event loop so it didn't block anything you would use a Web Worker or Worker thread depending on what JavaScript runtime you were using.
I'm learning node js callbacks and asynchronous behavior from this site. From the examples given, I've written following code to understand it better.
function callbackTester (callbackFn){
console.log('From callback tester.');
callbackFn();
}
function pollingWait(){
while (true) {}
}
callbackTester(() => {
console.log('From anonymous function.');
setTimeout(()=>{
console.log("I'm waiting!");
}, 500);
// pollingWait();
});
console.log('I am the last one');
Now, when I comment out pollingWait() function, it works as expected. It gives following output:
From callback tester.
From anonymous function.
I am the last one
I'm waiting!
Now when I comment out the setTimeout function and add pollingWait(), program goes in infinite loop. I think this is also an expected behavior as node js is single threaded and cannot avoid infinite loops. So how this asynchronous behavior works under the hood?
How it decides to when to continue execution and when not to? Is it possible to make my own function which acts as asynchronous like setTimeout?
I think this is also an expected behavior as node js is single threaded and cannot avoid infinite loops.
Node.js isn't single-threaded anymore, but there is just one main thread unless you create worker threads.
So how this asynchronous behavior works under the hood?
Node.js's main thread works on a loop: Your top-level code runs and returns, then any queued action (such as a timer callback) is run and returns, and then the next queued action runs and returns, etc. That's how setTimeout works: When it's time for the timer to fire, the event loop sees that and queues a call to the timer callback. Also note that while Node.js has only one main JavaScript thread by default, that doesn't mean Node itself is single-threaded. In particular it may do I/O processing on another internal thread.
Is it possible to make my own function which acts as asynchronous like setTimeout?
Only by using something that already provides asynchronous behavior and wrapping it. Those would include:
setTimeout
setImmediate
process.nextTick
A promise's then or catch callback
At first glance you might think async functions do that, but they don't, really: The code in an async function runs synchronously up until the first time it waits on a promise resolution (or up until it returns). So the asynchronousness is really just the same as the last bullet point above: A then or catch callback.
What you can't do (without a worker thread) is busy-wait like your pollingWait does, because nothing else can happen on the thread that busy-wait is running on.
Try this thing:
let done = false;
setTimeout(() => {
done = true
}, 5);
const eventLoopQueue = () => {
return new Promise(resolve =>
setImmediate(() => {
console.log('event loop');
resolve();
})
);
}
const run = async () => {
while (!done) {
console.log('loop');
await eventLoopQueue();
}
}
run().then(() => console.log('Done'));
Say we have a function.
function kevin(cb){
//Ok then, so async stuff here, then, when done,
cb(1); <== reply;
}
Then :
....
kevin(x=> console.log(x));
Then another block calls kevin() before the above call receives a reply.
kevin(y=> console.log(y));
I'm a bit confused after working with Java for a while, with the above, in java, if these callbacks were Java Interfaces, and the second call to kevin happened before the first call was returned, the second call would override the first, and only the second would be returned, requiring the composite pattern to make sure that all callbacks are recorded and fulfilled when the method is done.
But in Javascript, I'm not getting any errors, everything works and all function callbacks that call kevin() are being called.
I'm doing this in Angular with typescript. So the above are actually methods in classes.
Subsequent function calls will not in any way replace previous function calls. If some asynchronous event is awaited inside a function, then a new callback is scheduled on the event loop for each await. Simple example:
setTimeout(() => console.log(1));
setTimeout(() => console.log(2));
setTimeout(() => console.log(3));
All three callbacks will fire with their respective values.
The only time you will get interference is if you have shared variables:
let foo = 'bar';
setTimeout(() => console.log(foo));
setTimeout(() => foo = 'baz', 500);
setTimeout(() => console.log(foo), 1000);
The result of the last callback may or may not be what you expect, if you're unaware that the shared foo is being manipulated in another callback.
I can't seem to reconcile the technical flow of javascript execution sequence and the concept of callbacks. I have been using callbacks, but I am uneased of the execution flow because it appears that there are contradictions between idea of callback and the sequential javascript execution. This link http://cwbuecheler.com/web/tutorials/2013/javascript-callbacks/ explains callback and give examples, but I as I follow the code, I see a contradiction.
getData('http://fakedomain1234.com/userlist', writeData);
document.getElementById('output').innerHTML += "show this before data ...";
function getData(dataURI, callback) {
var myData = getSomeData(); // fake function
callback(myData);
}
function writeData(myData) {
document.getElementById('output').innerHTML += myData;
}
my question/observation is that inside the function getData, the callback(myData) statement does not get executed until after the function getSomeData() is finished and returned a value to the variable myData, but then the contradiction occurs when the document.getElementById... statement is allowed to execute before the getData function call is finished executing.
Am I missing something?
TIA
Synchronous vs. Asynchronous Execution
I think you're getting those two things mixed up. I'll quote and correct you below:
the callback(myData) statement does not get executed until after the function getSomeData()
Correct. This is synchronous (line-by-line) execution.
the document.getElementById... statement is allowed to execute before the getData function call is finished executing.
Incorrect. Again, this is synchronous execution - 'show this before...' will be inserted after the data.
You're likely thinking about callbacks in the context of asynchronous execution. Compare your synchronous code to this asynchronous version, which does insert 'show this ...' before the contents of myData:
getData('http://fakedomain1234.com/userlist', writeData);
document.getElementById('output').innerHTML += "show this before data ...";
function getData(dataURI, callback) {
//var myData = getSomeData();
//callback(myData);
getSomeDataAsync(callback);
}
function writeData(myData) {
document.getElementById('output').innerHTML += myData;
}
The change is in the getData function. callback is passed as an argument, rather than called immediately with the () operator.
The getSomeDataAsync function is asynchronous, meaning it will pop itself in the run loop's "background" before executing your myData callback. It won't run your callback until the event it is waiting for fires (i.e. when data retrieval completes). While getSomeDataAsync is waiting, execution resumes on the code that called it, which will insert your 'show this before...' immediately.
When the completion event fires, execution will resume, and the passed callback parameter will be executed. The contents of myData will then be appended!
Check out this fiddle to see what I mean
document.getElementById cannot be executed before getData gets completely executed, unless getData is asynchronous. By seeing there's a URL passing to getData tells me you are doing AJAX which is asynchronous.
Although your code won't behave like you said (it's synchronous!) because var myData = getSomeData() is synchronous, pretending the whole getData function is async and the flow goes like this:
Executes getData.
getData does its internal stuff and returns undefined.
Proceeds to document.getElementById.
Later getData gets its data and the browser or other environment executes the callback function passed to it before.
Executes statements inside writeData.
There are many ways that can create an async function, such as events, AJAX, and other timers (setTimeout/Interval).