I am studying async and await in javascript, and a little bit confused about the execution order of the following function I wrote when I play around async and await:
const promiseA = new Promise((resolutionFunc, rejectionFunc) => {
setTimeout(() => resolutionFunc(666), 5000);
});
const test = async () => {
await promiseA.then((val) =>
console.log("asynchronous logging has val:", val)
);
};
const testTwo = () => {
test();
console.log("immediate logging");
};
testTwo();
my understand is that in function <testTwo()>, <test()> execute first, it's been called & executed, <test()> is an async function, and I have put the await in front of the promise.
why this console.log("immediate logging"); line of code get executed first?
on the other hand, if I wrote <testTwo()> like following:
const testTwo = async () => {
await test();
console.log("immediate logging");
};
everything is fine
Related
I'm trying to curry a function but when the first one is async it throws the error function1(...) is not a function, however if I pass the async function as the last one it works fine.
Can anyone tell me why this is happening? and how to properly make a curry function that starts with a async function?
Thanks to anyone who take the time.
//This one is throwing the error: function1(...) is not a function
async function function1(path) {
const fetchedElement = await fetchElement(path);
//(...)
return (msg) => {
console.log(msg);
};
}
function1('somepath.html')('my message');
//This one works fine, properly returning other function
function function2(path) {
return async (msg) => {
const fetchedElement = await fetchElement(path);
//(...)
console.log(msg);
};
}
function2('somepath.html')('my message');
It depends on when the async work needs to get done. If you want the currying process to do the async work, then you can't invoke the currying function synchronously:
curryingFunction(paramA)(paramB)
^ assumes curryingFunction is synchronous
Instead, use two statements by the caller, one to await the currying, the other to invoke...
const fetch = path => new Promise(resolve => setTimeout(() => {
console.log('fetched ' + path)
resolve()
}, 1000));
async function curryingFunction(path) {
const fetchedElement = await fetch(path);
return message => {
console.log(message);
}
}
async function someCaller() {
// await to get a curried function, then invoke it
let curried = await curryingFunction('some_path');
curried('some message');
}
someCaller()
On the other hand, you might not need to do the async work in order to get the curried function. You probably don't. In that case, you can make the currying function synchronous, but have it return an async function that does the async work.
As a result, you'll get to use the fn()() syntax that you're probably used to using...
const fetch = path => new Promise(resolve => setTimeout(() => {
console.log('fetched ' + path)
resolve()
}, 1000));
function curryingFunction(path) {
return async (message) => {
const fetchedElement = await fetch(path);
console.log(message);
}
}
async function someCaller() {
// here we can use the fn()() syntax that we're accustomed to
await curryingFunction('some path')('some message')
}
someCaller()
As the first function is async You need to await it first, then call the second parameter.
//This one is throwing the error: function1(...) is not a function
async function function1(path) {
const fetchedElement = await Promise.resolve(1);
//(...)
return (msg) => {
console.log(msg);
};
}
(async () => {
try {
(await function1('somepath.html'))('my message');
} catch(e) {
console.log(e)
}
})()
I have this cloud function:
const initCompress = async () => {
try {
logger.log('This shows before the function terminated');
await mkdirp('../../../xxxxx'); <<<< WHY IS IT NOT WAITING FOR THIS TO COMPLETE?
logger.log('This shows after the function terminated');
return { success: true };
} catch (err) {
...
} finally {
...
}
};
export default initCompress;
It is executed via:
const main = async () => {
exports.compressImage = functions.https.onCall((data, context) => {
initCompress(data, context);
});
}
The console log shows:
functions: Beginning execution of "compressImage"
> {"severity":"INFO","message":"This shows before the function terminated"}
functions: Finished "compressImage" in ~1s
> {"severity":"INFO","message":"This shows after the function terminated"}
I'm probably doing something silly, but what? Do I need to await something somewhere?
What you observe is totally normal. By declaring a function as async, your make it return a Promise. That Promise is being returned immediately (it just doesn't resolve immediately). Your code is equivalent of this:
const mkdirp = () => Promise.resolve();
const logger = console;
const modifyImage = () => {
logger.log('This shows before the function terminated');
return mkdirp('../../../xxxxx')
.then(() => logger.log('This shows after the function terminated'))
.then(() => ({ success: true }))
.catch(logger.error);
};
modifyImage().then(logger.log);
logger.log('Function finished');
As a conclusion, never forget that async/await is just syntaxic sugar over Promises
Even after reading several answers to similar questions (e.g. this and that) I unfortunately still do not understand, why this code does not await the promises and hence logs ['check2'] last after the other checkpoints.
This is a minimal example using code from this guide. In the original code I need to fetch some Information from different sources before my express server can start listening.
console.log("check1");
const resolveInTwoSeconds = () => {
return new Promise((resolve) => {
setTimeout(() => resolve("check2"), 2000);
})
};
async function test() {
const asyncFunctions = [
resolveInTwoSeconds()
];
const results = await Promise.all(asyncFunctions);
console.log(results);
}
(async() => await test())();
console.log("check3");
EDIT:
Imagine "check3" to be a lot of code that is depended on the sideeffects of test().
Thus I want it to run after check2 was printed.
However I am using await here so I do not have to change or move "check3".
This line of code declares an async function and executes it:
(async() => await test())();
So far nothing waits for its result and the execution goes on to console.log("check3").
You have to explicitly wait for it:
await (async () => await test())();
Now, this won't work yet, because the top-level function is not async. Whenever you need to call await, you have to make sure it's called inside an async function. One way to do this would be to wrap everything inside another async function:
(async () => {
console.log("check1");
const resolveInTwoSeconds = () => {
return new Promise((resolve) => {
setTimeout(() => resolve("check2"), 2000);
})
};
async function test() {
const asyncFunctions = [
resolveInTwoSeconds()
];
const results = await Promise.all(asyncFunctions);
console.log(results);
}
await (async ()=> await test())();
console.log("check3");
})()
Otherwise, move your check3 into an async function you already have, as others suggested.
This should do what you want. you need the console.log to be inside the async function.
console.log("check1");
const resolveInTwoSeconds = () => {
return new Promise((resolve) => {
setTimeout(() => resolve("check2"), 2000);
})
};
async function test() {
const asyncFunctions = [
resolveInTwoSeconds()
];
const results = await Promise.all(asyncFunctions);
console.log(results);
}
(async() =>{
await test();
console.log("check3");
})();
const function1 = () =>
new Promise(function(resolve,reject) {
setTimeout(() => {
resolve(10)
},6000)
});
const function2 = async () => {
console.log("first");
const val = await function1()
console.log("second");
return val
}
console.log("third -- " ,function2())
I was exepecting the order of the message as below:
first
second
third -- Promise { <pending> }>
But it turns out to give the below output:
first
third -- Promise { <pending> }
second
can anyone please help me understanding this ?
rather than calling function2() you need to await on it
await function2(); // logs first (6 seconds expire) second, 10
this is because you need to wait for function 2 to resolve the Promise before proceeding
you could do the following for the desired result
const function3 = async () => {
const third = await function2();
console.log( "third --", third )
}
function3();
explanation of your code
console.log("first"); - goes first, I hope that there is no questions
when interpretator see this line const val = await function1() - it waits here and continue to execute synchronous code with is console.log("third -- " ,function2()) and you can see third -- Promise { <pending> }
than promise is resolving and execution of async part continues and you finally can see console.log("second");
to achieve expected behavior try this:
const function1 = () =>
new Promise(function(resolve,reject) {
setTimeout(() => {
resolve(10)
},6000)
});
const function2 = async () => {
console.log("first");
const val = function1()
console.log("second");
return val
}
console.log("third -- " , function2())
It's in the logs buddy :)!
The log with the word third is logged second. Because the log with the word 'second' is resolved inside function2 which is called as a normal function. This code basically assumes you're not interested in the (async) result of function two, so it just retuns the pending promise.
Whenever you want the result (and not the pending promise) of an async function you should always await it of chain a then() where you can log the final result, which in this case is 10.
Try next code
const function1 = () =>
new Promise(function (resolve, reject) {
setTimeout(() => {
resolve(10)
}, 6000)
});
const function2 = async () => {
console.log("first");
const val = await function1()
console.log("second");
return val;
}
const start = async () => {
console.log("third -- ", await function2());
};
start();
This is my simple function in nodejs
const myFunction = async() => {
const exercises = await Exercise.find({ workoutId })
return exercises
}
const value = await myFunction()
But when I do await outside async function it throws an error
await is a reserved word
Now how do I wait for the value outside the async function? Do I need to use callback or .then? Then what is the use async and await?
You can't use await outside an async function.
one trick to 'bypass' this limit is to use async IFEE:
const myFunction = async() => {
const exercises = await Exercise.find({ workoutId })
return exercises
};
(async () => {
const value = await myFunction()
})()
Short answer to the main question: "Is it possible to use await outside async function" no.
But there's multiple ways to access the value of an async operation, for example
const myFunction = async() => {
const exercises = await Exercise.find({ workoutId })
return exercises
}
const execution = () => {
myFunction().then( ( exercises ) => {
console.log( exercises );
});
}
As async is a wrapper for Promises to access the result you need to use then and when the execution is completed that callback is fired.