Suppose I have the following code in a Node.js app:
var result = bar();
In case of while loop, there is usually no need to make it async, although you can make it async, if you will (e.g. you know it will take a long time to compute and you do not want to block your main thread). If the HTTP request or database query would not be async, the JS engine will just stop and do nothing until the result arrive, which is not a big problem in Node.js, but in case of web pages, this will freeze the UI, which will certainly anger some users.
There are several ways to solve async tasks
callback, that will be called as soon as the task is finished (usually it accepts callback for success and callback for error case).
event emitter. You attach callbacks to events, which this emitter will generate and these callbacks are then called by the emitter as the events occurs. This callbacks are noted as event listeners.
promiseof some future result. This promise has methods like
always(), through which you can register your callbacks. It's quite similar to event emitter, promises offers better data flow control, but when created, cannot be aborted.
You can distinguish async by the fact, that it do not returns the result immediately, but it usually allows you to register callbacks for later invocation, either via parameters/arguments, or via methods of returned object.
Note: in case of ES6 and ES7, there are no callbacks needed for async process, but I will not complicate this topic more with this new technology.
for loop does not allow you to register callbacks, it simply occupies JS engine and makes all the iteration as fast as it can.