Javascript - Change two function then/catch style into the async/await style - javascript

I'm try to understand how .then() function can get two arguments like this.
const promise = doSomething();
const promise2 = promise.then(successCallback, failureCallback);
or
const promise2 = doSomething().then(successCallback, failureCallback);
but I want to convert two arguments .then() to async/await like this.
const result = await doSomething()
// execute successCallback if success.
// execute failureCallback if failure.
This is the website that I'm trying to learn.
Mozilla Firefox Developer : Using promise
Mozilla Firefox Developer : Promise Chaining

When you await a promise that resolves, you directly get its value:
const result = await doSomething();
When you await a promise that rejects, it throws an exception that you can either let propagate back to the caller of the current function (as a rejected promise since all async functions return a promise and async functions turn uncaught exceptions into a rejected promise) or you can catch it yourself locally with try/catch.
try {
const result = await doSomething();
} catch(e) {
console.log(e);
}
It is not recommended to map promises to callbacks. It's much better to just return the promise and let the caller deal with the promise directly either with .then() or await.
If you really needed to map await to successCallback and failureCallback, then you would do this:
try {
const result = await doSomething();
successCallback(result);
} catch(e) {
failureCallback(e);
}
But, at that point, you may as well just use .then() since it's less code:
doSomething().then(successCallback, failureCallback);
But, as I said earlier, you generally don't want to map promises into callbacks. It's more likely that you wrap older callback-based APIs into promises so you can use promises for all your control-flow and not mix/match models (which tends to seriously complicate good error handling when you mix models).

You can wrap the doSomething in a try catch method to capture the success and fail like this.
try {
const result = await doSomething()
} catch (err) {
console.log(err.message)
}

Use try...catch
try {
const result = await doSomething()
// success
successCallback();
}
catch (e) {
// error
failureCallback();

Related

Firestore Transactions - Is it necessary to await for all transaction actions?

I have read this code in the Firestore documentation:
const cityRef = db.collection('cities').doc('SF');
try {
const res = await db.runTransaction(async t => {
const doc = await t.get(cityRef);
const newPopulation = doc.data().population + 1;
if (newPopulation <= 1000000) {
await t.update(cityRef, { population: newPopulation });
return `Population increased to ${newPopulation}`;
} else {
throw 'Sorry! Population is too big.';
}
});
console.log('Transaction success', res);
} catch (e) {
console.log('Transaction failure:', e);
}
but I can't understand the purpose of awaiting the t.update() of the 8th line.
Wouldn't the code work the same way without awaiting for that 8th line?
I can't understand the purpose of awaiting the t.update() of the 8th
line. Wouldn't the code work the same way without awaiting for that
8th line?
You are totally right: the update() method (as well as the set() and delete() ones) is not asynchronous and does not return a Promise, but the Transaction.
When you call js async function you get a Promise object returned, which can tell you about the PromiseState (if function finished it's runtime) and PromiseResult (function's returned value).
The fact that the Promise object has returned does't tell you that the function finished it's mission.
The 'await' keyword makes your code stop until the async function finished running (similar to std::thread::join method).
Using 'await' with a Promise object can tell you for sure that your Promise has resolved, so (if the code didn't throw an exception) the lines after it can run safely, knowing that the async function ran successfully.
The use of the await at the t.update Promise is necessary and you should keep it there, elsewise you may return a success string for a code that still runing and might fail.
Note that the await keyword checks for finished Promise.PromiseState, and evaluates the Promise.PromiseResult value (undefined for non-returning functions)
Read Also:
JavaScript Async on W3Schools
Async Function on MDN

What if we do not wait for an asynchronous javascript function?

What if we do not wait for an asynchronous javascript function?
As far as I know some languages like C # should not run an asynchronous function unmanaged!
I wanted to know if this is also true for the JavaScript language?
var asynchronousFunction = async function() {
//...
}
function main() {
var result = true;
//...
asynchronousFunction(); // The result of this function has no effect on our output (result)
//...
return result;
}
It's run just the same. (In fact, you never await a function, you await for the the Promise it returns.)
The asynchronous function is run synchronously until the first await or return within it, at which point a Promise is returned to the caller and the rest of the function is arranged to run later.
It's up to the caller to do something (or nothing) to the Promise. After all, you might wish to store the promise in an array and await for the lot of them (Promise.all) or do something more esoteric about it, so JavaScript itself doesn't care.
Some smart enough IDEs and linters are able to raise a warning about unhandled promises, though, especially if you have enough type information to do so (e.g. by using TypeScript).
It's true for javascript as well.
You don't want to just create a promise and leave it totally hanging, if there are errors then they become unhandled errors and if it exits unexpectedly then you have no way of knowing that.
What I recommend is using the Promise.race at the top level and then it will run all of your async functions in parallel but will exit if any one of them exits unexpectedly.
async function worker() {
while (true) {
// do background work in a loop
}
}
async function server() {
await init()
await listen()
}
function main() {
const p0 = worker()
const p1 = server()
try {
await Promise.race([p0, p1])
console.log('done')
return true
} catch (err) {
console.log('The server had an error unexpectedly', err)
return false
}
}
If you expect the promises to eventually exit gracefully then use Promise.all instead, which will wait until all promises exit successfully before resolving.

How does using async/await differ from using Promises?

Recently I started using (Async & Await). Before this, I used Promise to make my process Asynchronous. Like:
example.firstAsyncRequest()
.then(firstResponse => {
return example.secondAsyncRequest(firstResponse)
})
.then(secondResponse => {
return example.thirdAsyncRequest(secondResponse)
})
.then(result => {
console.log(result)
})
.catch(err => {
console.log(err)
})
Now I am achieving this like:
try {
const firstResponse = await example.firstAsyncRequest();
const secondResponse = await example.secondAsyncRequest(firstResponse);
const thirdAsyncRequest = await example.thirdAsyncRequest(secondResponse);
console.log(thirdAsyncRequest)
}
catch (error) {
// Handle error
}
In both, the code-block method executes one after another and finally throws an error if any and gets caught by catch block. My question is, is this only a difference of syntax? Please explain or suggest me any link to understand this better.
Thank You
Is there only difference of syntax?
Yes. Your examples are functionally equivalent except that your second example is missing
console.log(thirdAsyncRequest);
...after the third await. (That variable really should be result to match the first code block, or thirdResponse to match the other two response variables).
async/await is syntactic sugar around promise creation and consumption. It's really helpful sugar, but that's all it is. async functions return promises. await expressions let you wait for a promise to settle, either getting the fulfillment value if it's fulfilled or throwing an error if it's rejected. (Since rejections are errors, you can use try/catch to handle them.) An uncaught error in an async function (whether a synchronous error or a promise rejection observed by await) causes the promise the async function returned to be rejected with that error. Otherwise, the function's promise is resolved to whatever the function's code returns: if it returns a non-thenable, the promise is fulfilled with that value; if it returns a thenable, the promise is fulfilled or rejected based on the settlement of that thenable.
(Re "resolve" vs. "fulfill" and such, I've written up this post on promise terminology.)

Is there difference between return with await or without

I'm just thinking about we need to use the await operator, and what is the difference between the following two case.
one
public async updateOne(Model, doc, errorMsg?){
return await Model.findOneAndUpdate({'_id': doc._id}, {'$set': doc}, {upsert:true, new: true}).lean().exec();
}
two
public updateOne(Model, doc, errorMsg?){
return Model.findOneAndUpdate({'_id': doc._id}, {'$set': doc}, {upsert:true, new: true}).lean().exec();
}
I think there is no difference in the result, but I think it is completely unnecessary to use the async await, because a promise will be returned, and we only need to use the await operator when we call the updateOne function inside an async function.
As Oyverus answered, there's no difference in the result but using async functions will create another Promise, I've added some rough examples to each case.
Using async updateOne(){ return await Model.findOneAndUpdate(...) } results in Promise code something like:
return new Promise((resolve, reject) => {
Model.findOneAndUpdate(...).then(resolve, reject)
})
Then async updateOne(){ return Model.findOneAndUpdate(...) } is:
return new Promise(resolve => resolve(Model.findOneAndUpdate(...))
A plain updateOne(){ return Model.findOneAndUpdate(...) } is:
return Model.findOneAndUpdate(...)
I tend to use the plain return when possible, but leave an /*async*/ in the code for documentation purposes.
/*async*/ write(){
return this.db.write()
}
In this use case, there isn't a difference in the eventual result, but there is a difference in how it works.
Returning an awaited promise in an async function will return another promise that gets resolved with the value of the awaited promise, which is basically two promises, which in this use case is redundant, since you're not doing any extra processing on the promise.
Returning a promise in a regular function will just return that promise as is, and won't wrap it around another promise, so you're completely right that it is unnecessary to use async await in this way.
Is there difference between return with await or without? ... I think there is no difference in the result
Yup, you got it right. In your example there is no difference.
From MDN:
When an async function is called, it returns a Promise. When the async function returns a value, the Promise will be resolved with the returned value. When the async function throws an exception or some value, the Promise will be rejected with the thrown value.
An async function can contain an await expression, that pauses the execution of the async function and waits for the passed Promise's resolution, and then resumes the async function's execution and returns the resolved value.
we only need to use the await operator when we call the updateOne function inside an async function.
Not exactly, the async operator just enables the use of await within the corresponding function and all the await operator does within that async function is unwrap a promise to the value it would return within the .then(value => /* do stuff with value */) callback. The purpose is so the code resembles a more familiar synchronous control flow.
The result of any invocation of a async function (i.e. the return type of it) will be a Promise of whatever you returned but note you can still use unwrapped promises (i.e. without await) within async functions, the values will just be wrapped in promises.
Let me know if you still need help understanding. I'll revise this post.
function simplePromise() { return Promise.resolve('resolved value'); }
async function asyncAwaitTest() {
const simplePromiseValue = await simplePromise();
console.log(simplePromiseValue); // resolved value
// if you don't use the `await` keyword, then the promise will still be a promise
simplePromise().then(value => console.log(value));
}
asyncAwaitTest();
The only diffrent is memory usage, which return await use more since an intermediate Promise object might be created.
The other good thing about Async/Await is that it allows us to catch any unexpected errors in a good old try/catch block. We just need to wrap our await calls like this:
async function doSomethingAsync(){
try {
// This async call may fail.
let result = await someAsyncCall();
}
catch(error) {
// If it does we will catch the error here.
}
}
The catch clause will handle errors provoked by the awaited asynchronous calls or any other failing code we may have written inside the try block.
You are correct that you don't need to use an async function when the only return value is the result of applying an await operator. Returning the promise operand of the await from a synchronous function that does not use await elsewhere is equivalent (as you coded in example "two").
The logic chain of
we only need to use the await operator when we call the updateOne function inside an async function
however is not exact. You can return the promise from within an async function without using await as in
three
public async updateOne(Model, doc, errorMsg?){
return Model.findOneAndUpdate({'_id': doc._id}, {'$set': doc}, {upsert:true, new: true}).lean().exec();
}
where the promise returned by Model will be used to resolve the promise returned by async.

How make promise execute synchronously?

I use dom-to-image.js for converting dom to png image. As dom-to-image.js uses promise, the code executes asynchronously. I want to execute .then function synchronously.
I have the following code:
domtoimage.toPng(document.getElementById("main")).then(function(dataUrl) {
console.log(dataUrl);
}).catch(function(error) {
console.error('oops, something went wrong!', error);
});
console.log("this console should be executed after console.log(dataUrl)")
I want to execute .then function first, before executing console.log("this console should be executed after console.log(dataUrl)").
Please tell me some way to achieve this.
There are of course legit reasons to force synchronous execution of a promise in js. The most obvious is when require'ing a file that needs to initialize using some asynchronous stuff, and optimization is not an overriding concern.
Seems like the package synchronized-promise seems like it ought to do the trick. In your case (warning - untested..):
const dti = () => docstoimage.toPng(document.getElementById("main"))
.then(dataUrl => console.log('url: ', dataUrl))
.catch(err => console.error('oops: ', err))
const sp = require('synchronized-promise')
const syncDti = sp(dti)
syncDti() // performs the 'synchronized version'
console.log("this console should be executed afterwards")
You didn't mention if it's done in browser or in NodeJs. For NodeJs that's possible by using execSync or spawnSync from child_process:
import { spawnSync } from "child_process";
function doSyncStuff(domObj){
const output = spawnSync(...);
console.log("this logs in server");
return output;
bit of a necro, but I'm the author of https://www.npmjs.com/package/synchronous-promise - which was around before this question was raised and does what you want (:
Async functions are a promise.
You have to use the promise syntax with them or use await (async-await syntax) on them in another async function.
An example of the regular promise syntax would be: myPromise.then(() => {})
For what you are looking for, you can use the promise syntax on them to wait for them as if they aren't a promise. Do take care though, as the code in myPromise.then(() => {}) is synchronous and can't use async-await features. I've wrapped things in a main function but you don't need to for extra code but you don't need to.
You can then run the main function through the promise method.
For e.g:
async function myFunction() {
// Do stuff
}
async function main() {
// Do stuff
await myFunction()
}
async function mySecondaryFunction() {
// Do stuff
}
function mySynchronousFunction() {
console.log("hello")
}
main().then(() => {
mySynchronousFunction()
mySecondaryFunction().then(() => {
console.log("idk")
}
})
See, we can use both types of functions!
Do know, though that this doesn't actually make promises synchronous.
It just acts like they're synchronous.
EDIT: Uhhh, I just realized you could put the console.log you want to execute after in both the try and catch functions.
For those stumbling upon this now:
If you're not concerned with IE support, you could use async and await to execute the promise as though it were synchronous. The await syntax will pause execution of the function until the promise resolves, letting you write the code as if there wasn't a promise. To catch an error, you wrap it in a try/catch block.
The only catch is that using the await syntax requires you to wrap it inside a function declared with async.
async function toPng() {
try {
let dataUrl = await domtoimage.toPng(document.getElementById("main"));
console.log(dataUrl);
}
catch (error ) {
console.error('oops, something went wrong!', error);
}
console.log("this console should be executed after console.log(dataUrl)")
}

Categories

Resources