Javascript while loop in async function is not async? - javascript

So I tried doing something like this
async function() {
while (x) {
}
// code
}
The reason I want to do this is because I need something to be done only when X becomes false, and I want it to be in another thread so my website is still usable, and according to the naming and what I read about it, async function should be async... It's only natural right?
But instead, my application is completely frozen when the while loop is running. Can someone please explain why this happens and if there's a way around it?
Thank you.

async does not mean multithreading, it just means that you can use the await keyword it it and that the value returned by that function is guaranteed to be a Promise, that its result will always be resolve/rejected in an asynchronous way.
So if the code within the async function does not utilizes any other asynchronous code then it would block the rest of the code the same way as a regular function would do.
If you use await within your while loop, then other code that is waiting could interleave at that point.
async function() {
while (x) {
// ...
await someFunction() // at this `await` other code could be executed
// ...
}
// code
}
So a await in the async function does two things, if the right side of the await is a Promise, then it will wait until it is resolve (or rejected) and it will allow other code that is scheduled to be executed to interleave.

I just wanted to share how I fixed my issue. It might not be the cleanest solution or the right solution, but it did just what I wanted with no performance issues.
All I wanted is to make a while loop that doesn't interrupt my code and at least seems like it runs asynchronously... and the async keyword wasn't what I was hoping it was, and doesn't do anything close to it. Instead, I tried this solution and it worked perfectly.
setTimeout(function() {
while (true) {
if (x) {
break;
}
}
// code
}, 0);
It seems that when you type 0 for the delay in a setTimeout, it executes the function you pass to it only after all of the pending code has executed. And so, it makes it act like it's kind of an async function. It accomplished what I wanted and works seamlessly, so that's what's improtant. If there's a better simple solution, please inform me.
Thank you.

Related

Is there a way to execute asynchronous code inline within a synchronous function?

Whenever I look for async/await JavaScript examples called from within a synchronous thread, I always see the following structure:
async fun = () => {
// async stuff like await statements
console.log("Done!")
}
fun() // Will print "Done!" when the end of the process has been reached
However I've recently come across a situation where I would want to write code inline without explicitly declaring a function and then calling it (avoids passing arguments if the function is declared in a higher scope and in my opinion is cleaner). I've found this solution to work, but I don't like it as it's essentially the same thing, simply the function isn't given a name:
(async () => {
// async stuff like await statements
console.log("Done!")
}).call() // Will also print "Done!" when the end of the process has been reached
Is there a better way to execute inline asynchronous code ? I looked at using the Promise API, notably Promise.resolve() but it doesn't seem to execute an asynchronous function passed to it, it's quite likely I still don't understand how it works.
I usually use IIFE
(async () => {
// async stuff like await statements
console.log("Done!")
})()

Why don't this function fire?

Today I have had this weird problem where in this function actions.order.capture(), it doesn't fire:
actions.order.capture();
this.props.handlePaymentComplete(data.orderID);
But when I use it like this it works:
actions.order.capture().then(() => {this.props.handlePaymentComplete(data.orderID);})
I understand that in the later case it waits for actions.order.capture() to end, and I would have understood if there was any connection between the result of actions.order.capture and the later function, but they are not dependent on each other's value, and when the second function fired before waiting to the first one to end, the first one doesn't fire at all.
What may be the case?
Looks to me it is asynchronous, .then() is called after the Promise resolved.
You should use the code bellow in an async function :
await actions.order.capture();
this.props.handlePaymentComplete(data.orderID);
Make sure it is in an async function. If not, the function will be called but the program won't stop to wait the answer ... So it will execute everything you wrote then close the process and you'll never get an answer. "await" makes the program wait for the answer, but it must be in an async function like this:
async function () {
await .....
}

Use await outside async

Is there a way to make the javascript await keyword work outside async functions? I would like to be able to freeze the entire call-stack (instead of just the rest of the async function), to be resumed once the particular promise returns a value. Sadly a powerful await like that is currently gimped or not implemented yet. I tried to make nodent.js work, but due to my custom loader and dynamic functions it's unfortunately impractical.
Is there a way to make the javascript await keyword work outside async functions?
Sadly, the answer is: No.
See the docs:
The await expression causes async function execution to pause, to wait for the Promise's resolution, and to resume the async function execution when the value is resolved. [emphasis added]
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await
I would like to be able to freeze the entire call-stack (instead of just the rest of the async function), to be resumed once the particular promise returns a value.
But how could your promise return a value if the entire call-stack was frozen? It would be stuck forever.
More details
To use await you need to be inside async function.
At least you have to do:
async function main() {
// use await here
}
main();
in your main code.
Or, using an IIFE - thanks to Robert Klep for the suggestion:
void async function main() {
// use await here
}();
Or, if you like punctuation:
(async () => {
// use await here
})();
Other options
There are some other options to handle concurrency in Node, like:
https://www.npmjs.com/package/co
https://www.npmjs.com/package/bluebird-co
https://www.npmjs.com/package/async-co
http://bluebirdjs.com/docs/api/promise.coroutine.html
http://taskjs.org/
none of which will freeze the call stack, however, as it would have the same effect as running kill -STOP with your own process ID and waiting for the stopped process to resume itself.
Given you are looking for a hack, not a proper promise-based concurrency solution, have a look at node-fibers (there are similar ones, but afaik this is the most popular, with multiple abstractions built around it). It does allow you to halt the current fiber in any synchronous function until something asynchronous happens that runs in a different fiber. Which of course is a horrible idea, but well…

Definition of a JavaScript promise and what is the difference to an event?

I've dealt with JavaScript years ago. So I'm familiar with the term "event" as an function which is automatically executed when a certain event happens. Please correct me in case my definition is wrong.
Now I have to deal with the language again. Try to get an idea from this promise-thing which is new to me. But can't find any good definition for it.
Can anyone give an easy to understand definition of what JavaScript promises are?
More over: They seem to me very similar to events. You define a callback-function which is automatically called when a certain event happens.
What's the difference between JavaScript-events and -promises?
For the first view, they are very similar. In events, you have a callback function, and in Promise you have a callback-function. Even more, technically, you can do almost similar stuff which Promises do only with Events.
Events and Promises both useful for Async code. I will write some abstract code to try explain. For example, you have some async code, and after that, it should alert something.
function someAsyncFunction() {
setTimeout(function() {
// some long async logic here
console.log('What the hell is Promises?');
}, 2000);
}
someAsyncFunction();
Timeout here is Async, because it will run your code not in main tread and run it after some time, you not sure when exactly it happens (ofcouse here it's around 2s. less-or-more).
So now imagine, that you need to do something with result of async action. For example you have function AsyncResultCalculator and you need to run that function. What you will do? You have few choices:
Pass a callback function to async code and run your function AsyncResultCalculator when async code complete it's work
Define some Event (for example 'DoSomethingAfterAsync' event) and trigger that event after async code is finished or failed.
Use promises
All this variants as result, will do only one thing - run your function AsyncResultCalculator. So, why we have 3 different ways to do the same result? Because it's cool! It's just different techniques to do the same stuff, but they change difficulty of your code. Some ways make your code more complicated, some ways make your code larger, some ways make your code more elegant.
So, i think you know how to run callback functions or how to trigger event, but what about Promises? How to use them? Very easy. Let's go back to Async Timeout and look:
function AsyncResultCalculator(res) {
// calculate result of async action!!!
console.log(res + 1);
}
function someAsyncFunction() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
// some long async logic here
resolve(55); // or reject
}, 2000);
}
}
someAsyncFunction().then(AsyncResultCalculator);
So, what the point to use Promises here? Just because it's modern style for async actions. With promises your code will be more elegant and more easy to read for different developers. Also, promises is useful because you can build a CHAIN of function like
someAsyncFunction()
.then(function(){ ... })
.then(function(){ ... });
But, of course, in some cases, it's not bad to use callbacks or events. For example, events is more useful, if you need to catch async result in some different JS file and you don't want to uses promises or callbacks in original file with async action.
All JavaScript language is mix of events, callbacks and promises ;D Use it with wise.
Use events for DOM events or some complicated situations.
Use promises for async actions
Use callbacks for sync actions or where you don't want to use Promises
At their most basic, promises are a bit like event listeners except:
A promise can only succeed or fail once. It cannot succeed or fail twice, neither can it switch from success to failure or vice versa.
If a promise has succeeded or failed and you later add a success/failure callback, the correct callback will be called, even though the event took place earlier.
Check out this JavaScript Promises: an Introduction

Blocking javascript functions (node.js)

I have this code:
var resources = myFunc();
myFunc2(resources);
The problem is that JavaScript calls myFunc() asynchronous, and then myFunc2(), but I don't have the results of myFunc() yet.
Is there a way to block the first call? Or a way to make this work?
The reason why this code doesn't work represents the beauty and pitfalls of async javascript. It doesn't work because it is not supposed to.
When the first line of code is executed, you have basically told node to go do something and let you know when it is done. It then moves on to execute the next line of code - which is why you don't have the response yet when you get here. For more on this, I would study the event-loop in greater detail. It's a bit abstract, but it might help you wrap your head around control flow in node.
This is where callbacks come in. A callback is basically a function you pass to another function that will execute when that second function is complete. The usual signature for a callback is (err, response). This enables you to check for errors and handle them accordingly.
//define first
var first = function ( callback ) {
//This function would do something, then
// when it is done, you callback
// if no error, hand in null
callback(err, res);
};
//Then this is how we call it
first ( function (err, res) {
if ( err ) { return handleError(err); }
//Otherwise do your thing
second(res)
});
As you might imagine, this can get complicated really quickly. It is not uncommon to end up with many nested callbacks which make your code hard to read and debug.
Extra:
If you find yourself in this situation, I would check out the async library. Here is a great tutorial on how to use it.
myFunc(), if asynchronous, needs to accept a callback or return a promise. Typically, you would see something like:
myFunc(function myFuncCallback (resources) {
myFunc2(resources);
});
Without knowing more about your environment and modules, I can't give you specific code. However, most asynchronous functions in Node.js allow you to specify a callback that will be called once the function is complete.
Assuming that myFunc calls some async function, you could do something like this:
function myFunc(callback) {
// do stuff
callSomeAsyncFunction(callback);
}
myFunc(myFunc2);

Categories