JavaScript: Using await to make asnyc code look more synchronous [duplicate] - javascript

This question already has answers here:
Combination of async function + await + setTimeout
(17 answers)
Closed 2 years ago.
I am trying to understand the asnyc await functionality.
Therefore, i want to use an asnyc function, resolve it and do the following logs sequentially afterwards.
How do I achieve this? Or am I understanding something fundamentally wrong?
const test = async function() {
console.log('hi 1');
await setTimeout(() => {
console.log('timout1')
}, 1000);
console.log('hi 2');
console.log('hi 3');
}
test()
Result
hi 1
hi 2
hi 3
timout1
Expected Result
hi 1
timout1
hi 2
hi 3

You can use await for promises only and the setTimeout function doesn't return a Promise. However you can await a Promise that is resolved using setTimeout like so which will give you the desired result.
So, the function execution will halt untill either the Promise being awaited gets resolved or gets rejected and then continue.
const test = async function() {
console.log('hi 1');
// return a new promise resolved after setTimeout callback is fired
await (new Promise((resolve, reject) => {
setTimeout(() => {
console.log('timout1')
resolve()
}, 1000)
}))
console.log('hi 2');
console.log('hi 3');
}
test()
Hope this helps !

I hope this code help you to understand async await.
function resolveAfter2Seconds() {
return new Promise(resolve => {
setTimeout(() => {
resolve('resolved');
}, 2000);
});
}
async function asyncCall() {
console.log('hi 1');
const result = await resolveAfter2Seconds();
console.log(result);
console.log('hi 2');
console.log('hi 3');
}
asyncCall();

Related

JS - Why code does not run after async / await for promise [duplicate]

This question already has answers here:
Why does nodejs stop execution of while true loop inside async function
(3 answers)
Closed 28 days ago.
I have a sample code on TS playground represents my problem.
In an async function, I log the result after await for the promise, but only the code inside promise run, not the log outside of it. Could someone explain this problem?
Here is the code:
const asyncFnc = async () => {
let result = false;
await new Promise(resolve => {
setTimeout(() => {
// This log worked
console.log('waited 5s');
result = true;
}, 5000);
});
// This log did not worked
console.log(result);
}
asyncFnc();
And the result:
await sends the parent function to sleep until the promise on the right hand side settles (i.e. resolves or rejects).
Your promise never resolves or rejects. (i.e. you don't call resolve, make use of the second argument, or throw an exception).
Thus the parent function sleeps forever.
The idiomatic way to write this would be to avoid setting variables in the wider scope as a side effect, and just resolve with the values instead.
const asyncFnc = async () => {
const result = await new Promise(resolve => {
setTimeout(() => {
console.log('waited 5s');
resolve(true);
}, 5000);
});
console.log(result);
}
asyncFnc();
You need to call resolve() in your timeout

Why should we store Promise objects in variables?

Let us suppose that we've got a function that resolves a promise like below:
function timeoutPromise(interval) {
return new Promise((resolve, reject) => {
setTimeout(function(){
resolve("done");
}, interval);
});
};
and let us suppose that we call that function inside an asynchronous function in two different ways;
slow synchornous way:
async function timeTest() {
await timeoutPromise(3000);
await timeoutPromise(3000);
await timeoutPromise(3000);
}
Here we simply await all three timeoutPromise() calls directly. Each subsequent one is forced to wait until the last one finished, this will result in total run time of around 9 seconds.
and fast asynchronous way:
async function timeTest() {
const timeoutPromise1 = timeoutPromise(3000);
const timeoutPromise2 = timeoutPromise(3000);
const timeoutPromise3 = timeoutPromise(3000);
await timeoutPromise1;
await timeoutPromise2;
await timeoutPromise3;
}
Here we store the three Promise objects in variables, which has the effect of setting off their associated processes all running simultaneously. This will result in total run time of around 3 seconds.
But the question is, why storing Promise objects in variables has the effect setting off their associated processs running simultaneously? what happens under the hood?
await foo();
await bar();
will only call bar (and thus create the second promise) after the promise returned by foo is resolved.
var x = foo();
var y = bar();
await x;
calls bar (and thus creating the second promise) before the promise returned by foo is resolved.
That's what makes the promises "concurrent". If you add console.log in various places you will see the difference in execution:
function timeoutPromise(name, interval) {
return new Promise((resolve, reject) => {
console.log(`Promise ${name} created.`);
setTimeout(function(){
console.log(`Promise ${name} resolved.`);
resolve("done");
}, interval);
});
};
async function timeTest1() {
console.log('test 1');
await timeoutPromise(1, 3000);
console.log('between promise 1 and 2');
await timeoutPromise(2, 3000);
}
async function timeTest2() {
console.log('test 2');
const timeoutPromise1 = timeoutPromise(1, 3000);
console.log('between promise 1 and 2');
const timeoutPromise2 = timeoutPromise(2, 3000);
await timeoutPromise1;
console.log('between promise 1 and 2 with await');
await timeoutPromise2;
}
timeTest1().then(timeTest2);

How to use async-await [duplicate]

This question already has answers here:
Combination of async function + await + setTimeout
(17 answers)
Closed 3 years ago.
I need to run various steps in a function but steps have to be run in a specific order. I tried to implement an Async function as follow:
async function test() {
await setTimeout(function() { console.log('1'); }, 5000);
await setTimeout(function() { console.log('2'); }, 2000);
console.log('3');
}
test();
The expected results in the console should be 1, 2, 3 but I get 3, 2, 1.
It seems that the await parameter is ignored.
EDIT
The setTimeout function is used in the illustrative example above only to simulate a heavy task. In my project, I will not use it. Indeed, I need to connect to a database then reformat the results before moving to the next steps. Even by including the async-await, 2 is logged-in before 1. In other words, empty lists are passed to my graphic because the async-await is not taken into consideration. Here my current code:
async function refreshData() {
myLabel = [];
myValues = [];
myJSON = [];
const sqlite3 = require('sqlite3').verbose();
let db = new sqlite3.Database(fullPath + '/annex/data.db');
await new Promise(resolve => {
db.each('SELECT firstName, age FROM Info;', function(err, row) {
console.log('1');
myLabel.push(row.firstName);
myValues.push(row.age);
myJSON.push(JSON.stringify(row));
});
resolve(myValues);
resolve(myLabel);
resolve(myJSON);
});
console.log('2');
db.close();
popChart(myLabel, myValues);
popTable();
}
You can write a wait function:
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
async function test() {
console.log('1');
await wait(5000);
console.log('2');
await wait(2000);
console.log('3');
}
test();
I've used the following
function wait(time) {
return new Promise((resolve) => setTimeout(resolve, time));
}
and then you just await this function in your method.
using this:
async function test() {
await new Promise(resolve => {
setTimeout(function() { console.log('1'); resolve(); }, 5000)
});
await new Promise(resolve => {
setTimeout(function() { console.log('2'); resolve(); }, 2000)
});
console.log('3');
}
test();
For using await on a function & waiting till the function executes, it must be running on a promise, so you can create a new function delay which calls setTimeout within itself but runs on promise, so it will return once the console is logged after timeout & the calling function will hold the execution until it gets the promise resolved
Read this for better understanding with more examples
function delay (val,time){
return new Promise((resolve,reject)=>{
setTimeout(function() { console.log(val); resolve(true) }, time);
});
}
async function test() {
await delay('1',5000);
await delay('2',2000);
console.log('3');
}
test();

Is there a method to fix async functions [duplicate]

This question already has answers here:
Combination of async function + await + setTimeout
(17 answers)
Closed 3 years ago.
Recently i have started to learn about async functions is JS
So i wrote a code that had to make a request, and with the data it received from the request, it should write in a CSV, the issue was that the write function hadn't waited for the request response, so it just wrote undefined.
In debugging purposes i wrote a new code to see how does async functions work, so i have the next situation
I have 3 functions log1(), log2(), main(),
I expect:
When I call main(), it should call log1(), wait until it finishes all the statements, and after that it should call log2()
So I wrote this code:
function slowFunction(){
setTimeout(() => {
console.log('1')
}, 2000);
}
function log1() {
return new Promise(resolve =>{
resolve(slowFunction())
})
}
function log2() {
console.log('2');
}
async function main() {
var aux = await log1();
log2();
}
main();
So I expected it to output
1
2
But it did output
2
1
I want to pay attention that I can't edit slowFunction, and you should perceive it like a function that needs an unknown amount of time to execute, so i need to wait for it that finishes, and after that the program should execute the log2();
The problem is with slowFunction. It appears you want slowFunction to resolve after the timeout, but it returns immediately as currently written. You need to rewrite slowFunction to return a Promise, or maybe just rewrite log1:
function log1() {
return new Promise((resolve) => {
setTimeout(() => {
console.log('1');
resolve();
}, 2000);
});
}
Make sure all async functions are wrapped with promise.
function slowFunction(){
return new Promise(resolve =>{
setTimeout(() => {
resolve("1")
}, 2000);
})
}
async function log1() {
let ret = await slowFunction()
console.log(ret)
}
function log2() {
console.log('2');
}
async function main() {
var aux = await log1();
log2();
}
main();

Javascript: how to run sequentially slow functions?

I am not an experienced Javascript programmer but I find it very difficult to execute 2 time-consuming functions in the row.
I have spent some days on studying promises or async/await but not success so far.
console.log("synch 1");
slowFunction1();
slowFunction2();
console.log("synch 2");
Most examples describe get json functions,setTimeOut etc. But in my case I have to do heavy mathematical calculations and the sequential execution is required. How could I do this?
Depends on what you're trying to achieve and what the environment is. I will assume the slow function is blocking and you're going for the main thread not to be blocked during execution. Assuming you are talking about:
Web:
Web workers would be your best bet (https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers)
Some example code would be:
var myWorker = new Worker('file-containing-slow-code.js');
myWorker.postMessage({execute: 'slowFunction1'});
myWorker.onmessage((msg) => {
const {result, functionExecuted} = msg.data;
console.log(result);
});
//contents of file-containing-slow-code.js
onmessage = function(e) {
var result = funcs[e.data.execute]();
postMessage({result, functionExecuted: e.data.execute});
}
const funcs = {
slowFunction1: () => {
// do slow stuff;
}
};
Node.js
Using child processes (https://nodejs.org/api/child_process.html#child_process_child_process)
You could wrap your functions in a promise like this, and only resolve when you want the code to continue:
function slowFunction1() {
return new Promise(resolve => {
setTimeout(() => resolve(), 1000)
})
}
function slowFunction2() {
return new Promise(resolve => {
setTimeout(() => resolve(), 1000)
})
}
console.log("synch 1");
slowFunction1().then(() => {
slowFunction2().then(() => {
console.log("synch 2");
});
})
This code should wait 1 second for each function before it console.log()'s "synch 2"
OR, you could use async/await instead of using .then(), like this:
function slowFunction1() {
return new Promise(resolve => {
setTimeout(() => resolve(), 1000)
})
}
function slowFunction2() {
return new Promise(resolve => {
setTimeout(() => resolve(), 1000)
})
}
async function main() {
console.log("synch 1");
await slowFunction1()
await slowFunction2()
console.log("synch 2");
}
main()
You got this right,you are trying to achieve a asychronous task.
Asynchronous Task
A task which will take some time to complete.
Way 1 - Callbacks
You need to give a callback to your further task.
Let me give you an example.
function myHugeTask(callback) {
// I need to do my task
console.log('Hey I am first task')
callback()
}
const someTaskWhichINeedToExecuteLater = () => {
console.log('Hey I am after the first task')
}
myHugeTask(someTaskWhichINeedToExecuteLater)
Way 2 - Promises
Promises is like a real world promise. If I promised you then I will either complete it or reject it.
Let see
const myHugeTaskPromise = new Promise(resolve => {
// Do my huge task no matter how much time it takes
console.log('I will complete first')
resolve()
})
myHugeTaskPromise.then(()=>{
console.log('Need to done when my promise get fulfilled')
})

Categories