Code execution not happening in asyn function [duplicate] - javascript

This question already has answers here:
How do I convert an existing callback API to promises?
(24 answers)
Closed 3 years ago.
In the following code the last line does not print ('end'):
function setTimeoutSync(fn, milli) {
return new Promise((resolve) => {
setTimeout(fn, milli);
});
}
async function run () {
console.log('start');
await setTimeoutSync(() => { console.log('setTimeoutSync'); }, 3000);
console.log('end');
}
run();
It is not that the script is exiting, because nothing I put after the await statement gets executed.
How can NodeJS just not execute statements in a function? Also, what's a good way to do a good old-fashioned synchronous wait in NodeJS? This question is actually more about the former than the latter.

Not sure if this is a typo but you forgot to call resolve so the next line after the await will execute:
function setTimeoutSync(fn, milli) {
return new Promise((resolve) => {
setTimeout(() => {
fn()
resolve()
}, milli);
});
}
async function run() {
console.log('start');
await setTimeoutSync(() => {
console.log('setTimeoutSync');
}, 3000);
console.log('end');
}
run();
As for your question:
Can you explain how not calling resolve can result in the rest of the
function not executing?...
Well async await uses generators and promise behavior:
The purpose of async/await functions is to simplify the behavior of
using promises synchronously and to perform some behavior on a group
of Promises. Just as Promises are similar to structured callbacks,
async/await is similar to combining generators and promises.
A generator can yield results thus not terminating the execution context, and can continue it where it left off.
Basically your example could be written with Promise.prototype.then() callback:
function setTimeoutSync(fn, milli) {
return new Promise((resolve) => {
setTimeout(() => {
fn()
resolve()
}, milli);
});
}
async function run() {
console.log('start');
setTimeoutSync(() => {
console.log('setTimeoutSync');
}, 3000)
.then((result) => {
console.log('end');
});
}
run();
So as you see, if we are not resolving, the callback to .then won't run.

Related

Does NestJS guarantee to run async methods after return?

What will happen when a code without await an async function returns from a REST API of NestJS?
// modified from https://stackoverflow.com/questions/59829254
#Post()
async create(#Body() body: Dto, #Headers('id') id: string) {
body.id = id;
const item = await this.service.create(body);
this.service.anotherAsyncMethod().then(...).catch(...);
return item;
}
In this example, does the process always live to run the complete anotherAsyncMethod?
If it does, how can it be? Do NestJS or Javascript itself guarantee the way to execute?
It seems there are some waitings in simple test code.
async function asyncFunction() {
setTimeout(() => console.log("after 3s"), 3000);
}
asyncFunction();
console.log('END');
// output
// END
// after 3s
But I could not find the clue that it always work in NestJS scenario and the others.
In JavaScript, any piece of code that comes before the return statement will be executed. Do not forget that the await statement will only wait for the result, and if you put await before an async operation, it will wait for its result, but even if you did not put await, the async operation still placed in the event loop and will still be executed.
The only principle is that all these operations should be before the return statement. The return means termination of that function. Not only in JavaScript but in all languages, nothing will be executed after return.
function someOperations(status) {
return new Promise((res, rej) => {
setTimeout(() => {
console.log(status)
res('done');
}, 3000);
});
}
(async () => {
console.log('start...');
await someOperations('first');
someOperations('second');
console.log('second someOperations skipped for now');
return;
console.log('unreachable'); // will not be executed
})()

Difference between returning 'fetch(...)' vs returning 'fetch(..).then(...)' [duplicate]

I'm trying to understand difference between these 3. Callbacks & Promises are clear but I don't get the usage of async/await. I know it is the syntactic sugar of promises but what I've tried didn't work. I'm sharing the piece of code I've tried to understand all this...
I've tried with an array
var array = [1,2,3];
and 2 functions
get() executes in 1 sec & console the array
post(item) executes in 2 sec & push a new item in the array
Now, what I want to get is that the post method should execute first & get after it so that the result on the console should be [1,2,3,4] not [1,2,3]
CALLBACK
function get() {
setTimeout(() => console.log(array), 1000);
}
function post(item, callback) {
setTimeout(() => {
array.push(item);
callback();
}, 2000);
}
function init() {
post(4, get);
// returns [1,2,3,4] ✅
}
It works fine but in case of too many callbacks, code will be messier... So,
PROMISE
function get() {
setTimeout(() => console.log(array), 1000);
}
function post(item) {
return new Promise((resolve, reject) => setTimeout(() => {
array.push(item)
resolve();
}, 2000));
}
function init() {
post(4).then(get);
// returns [1,2,3,4] ✅
}
Ok with much cleaner code. But still multiple then calls... Now,
Async/Await
function get() {
setTimeout(() => console.log(array), 1000);
}
function post(item) {
setTimeout(() => {
array.push(item)
}, 2000);
}
async function init() {
await post(4);
get();
// returns [1,2,3] ❌
await post(4);
await get();
// returns [1,2,3] ❌
post(4);
await get();
// returns [1,2,3] ❌
}
Much more cleaner version but neither way, it worked... I've also tried this (convert both functions (post & get) to async and call with then)
async function get() {
setTimeout(() => console.log(array), 1000);
}
async function post(item) {
setTimeout(() => {
array.push(item)
}, 2000);
}
async function init() {
post(4).then(get);
// returns [1,2,3] ❌
}
But still of no use. So I'm totally confused about this feature (i.e. async/await). Please elaborate on this very example. And also please tell me about Promise.resolve & Promise.all in this same context! Thanks
async and await are tools to manage promises
await post(4);
Here you are waiting for the promise returned by post to be resolved.
function post(item) {
setTimeout(() => {
array.push(item)
}, 2000);
}
However, post does not return a promise, so it does nothing useful.
You had a working implementation of post with a promise before. So use that:
function post(item) {
return new Promise((resolve, reject) => setTimeout(() => {
array.push(item)
resolve();
}, 2000));
}
Your attempts with async and await do not use anything that resolves a promise after a delay. As it stands, all the async functions you have defined, return a promise that immediately resolves.
You'll want to use a utility function that you can often use. It returns a promise that resolves after a given number of milliseconds, using setTimeout:
// utility function
let delay = ms => new Promise(resolve => setTimeout(resolve, ms));
let array = [1, 2, 3];
async function get() {
await delay(1000);
console.log(array);
}
async function post(item) {
await delay(1000);
array.push(item)
}
async function init() {
await post(4);
await get();
}
init();
console.log("wait for it...");
Similar to what you did in PROMISE.
Wrap post setTimeout in a promise and return it.
call resolve inside the body of the settimeout.
function post(item) {
return new Promise((resolve)=>{
setTimeout(() => {
array.push(item)
resolve()
}, 2000);
})
}
then you can use it like that :
async function init() {
await post(4);
get();
}

Function being executed in the wrong order [duplicate]

This question already has answers here:
Is there a way to wait until a function is finished in React Native?
(3 answers)
Closed 3 years ago.
I have this submit function that runs two functions when clicked on. My issue is that props.updateValues() is executed before createAffiliation(values)
How can I change the order of the execution?
const onSubmit = () => {
createAffiliation(values)
props.updateValues();
}
createAffiliation:
export function createAffiliation(anknytning: Anknytning) {
return axios
.post(Endpoints.affiliationData, anknytning)
.then((response: AxiosResponse<any>) => {
console.table("Created affiliation", anknytning);
return Promise.resolve(response.data);
})
.catch(reason => {
console.error("Could not create affiliation", reason);
return Promise.reject(reason);
});
}
As first function is returning a promise you can use .then() to let the first one finish:
const onSubmit = () => {
createAffiliation(values)
.then(()=>props.updateValues());
}
Or if you would like to see about Promise.race().
This happens because createAffiliation function returns a promise so we don't know when it will be resolved or rejected. Javascript will continue to execute your code, so props.updateValues() executes first.
There are 2 common way to resolve this issue.
1-) async await:
An async function can contain an await expression that pauses the execution of the async function to wait for the passed Promise's resolution, then resumes the async function's execution and evaluates as the resolved value.
The purpose of async/await is to simplify using promises synchronously. It can only be used inside an async function.
const onSubmit = async () => {
try {
await createAffiliation(values)
props.updateValues();
} catch (err) {
console.log(err);
}
}
2-) with then catch block you can do like this:
const onSubmit = () => {
createAffiliation(values)
.then(() => props.updateValues())
.catch(err => console.log(err));
};

Writing async/await version of a promise

The code below logs 'hello world' once in a second as expected.
function moveOneStep() {
return new Promise((res, rej) => {
setTimeout(() => {
res(console.log('Hello world!'))
}, 1000)
})
}
async function main() {
await moveOneStep();
await moveOneStep();
await moveOneStep();
await moveOneStep();
}
Considering the return value of an async function corresponds to what is returned from resolve function in promises, why doesn't the code below output the same result, but instead logs all the 'hello world's at once:
async function moveOneStepAsync() {
setTimeout(() => {
return console.log('Hello world!');
}, 1000);
}
async function main() {
await moveOneStepAsync();
await moveOneStepAsync();
await moveOneStepAsync();
await moveOneStepAsync();
}
That's because setTimeout does not return promise to await it in your main function. setTimeout itself executes synchronously. It adds to an event loop the callback that is passed as an argument to execute in time that is mentioned.
Also in this code return of your callback means nothing as callback with be run in 1 sec and the returned value will go nowhere.
async keyword tells you that functions returns promise and could have awaitable code in it. So as there is not await in your code it then looks like
function moveOneStepAsync() {
setTimeout(() => {
return console.log('Hello world!');
}, 1000);
return Promise.resolve();
}
So your await in main will await one event loop tick to go to the next "step"
Read about setTimeout, event loop, and what await expects to understand it more in-depth
You do not return anything to the function, you return back to the internal setTimeout function, and that does not do anything with that value. Calling setTimeout does not return a promise, it rather returns a timer immeadiately. And therefore all the moveOneStepAsync calls execute immeadiately, the timers get set, and fire after one second.

jQuery / Javascript function execution

I have 3 functions func1(), func2() and func3(). They are independent of each other. I would like to execute these 3 methods in parallel and with a single call back method. is it possible something like this
function parentMethod(){
call ([func1(),func2(), func3()],<callback function>);
}
Callback functionality is optional but can these 3 functions be executed in parallel.
Use a promise chain with Promise.all
Promise.all([func1, func2, func3]).then(values => {
//values from all the functions are in the callback param
});
Adding to the promise answer given, you'll need to "promisify" your functions if they don't already return promises (this demo assumes an error-first callback):
let promises = [func1, func2, func3].map(func => {
return new Promise((resolve, reject) => {
func((err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
})
});
});
Promise.all(promises)
.then((results) => {
let [func1Data, func2Data, func3Data] = results;
})
.catch(err => {
console.log('error!', err);
});
You can also use web workers but it'll be a little more verbose solution. You can check this post: HTML5/JS - Start several webworkers

Categories

Resources