try/catch blocks with async/await
I'm digging into the node 7 async/await feature and keep stumbling across code like this
async function main() {
try {
var quote = await getQuote();
console.log(quote);
} catch(error) {
console.error(error);
}
}
This seems to be the only possibility resolve/reject or return/throw with async/await, however, v8 doesn't optimise code within try/catch blocks?!
Are there alternatives?
Alternatives
An alternative to this:
async function main() {
try {
var quote = await getQuote();
console.log(quote);
} catch (error) {
console.error(error);
}
}
would be something like this, using promises explicitly:
function main() {
getQuote().then((quote) => {
console.log(quote);
}).catch((error) => {
console.error(error);
});
}
or something like this, using continuation passing style:
function main() {
getQuote((error, quote) => {
if (error) {
console.error(error);
} else {
console.log(quote);
}
});
}
Original example
What your original code does is suspend the execution and wait for the promise returned by getQuote()
to settle. It then continues the execution and writes the returned value to var quote
and then prints it if the promise was resolved, or throws an exception and runs the catch block that prints the error if the promise was rejected.
You can do the same thing using the Promise API directly like in the second example.
Performance
Now, for the performance. Let's test it!
I just wrote this code - f1()
gives 1
as a return value, f2()
throws 1
as an exception:
function f1() {
return 1;
}
function f2() {
throw 1;
}
Now let's call the same code million times, first with f1()
:
var sum = 0;
for (var i = 0; i < 1e6; i++) {
try {
sum += f1();
} catch (e) {
sum += e;
}
}
console.log(sum);
And then let's change f1()
to f2()
:
var sum = 0;
for (var i = 0; i < 1e6; i++) {
try {
sum += f2();
} catch (e) {
sum += e;
}
}
console.log(sum);
This is the result I got for f1
:
$ time node throw-test.js
1000000
real 0m0.073s
user 0m0.070s
sys 0m0.004s
This is what I got for f2
:
$ time node throw-test.js
1000000
real 0m0.632s
user 0m0.629s
sys 0m0.004s
It seems that you can do something like 2 million throws a second in one single-threaded process. If you're doing more than that then you may need to worry about it.
Summary
I wouldn't worry about things like that in Node. If things like that get used a lot then it will get optimized eventually by the V8 or SpiderMonkey or Chakra teams and everyone will follow - it's not like it's not optimized as a principle, it's just not a problem.
Even if it isn't optimized then I'd still argue that if you're maxing out your CPU in Node then you should probably write your number crunching in C - that's what the native addons are for, among other things. Or maybe things like node.native would be better suited for the job than Node.js.
I'm wondering what would be a use case that needs throwing so many exceptions. Usually throwing an exception instead of returning a value is, well, an exception.
Alternative Similar To Error Handling In Golang
Because async/await uses promises under the hood, you can write a little utility function like this:
export function catchEm(promise) {
return promise.then(data => [null, data])
.catch(err => [err]);
}
Then import it whenever you need to catch some errors, and wrap your async function which returns a promise with it.
import catchEm from 'utility';
async performAsyncWork() {
const [err, data] = await catchEm(asyncFunction(arg1, arg2));
if (err) {
// handle errors
} else {
// use data
}
}
async function main() {
var getQuoteError
var quote = await getQuote().catch(err => { getQuoteError = err }
if (getQuoteError) return console.error(err)
console.log(quote)
}
Alternatively instead of declaring a possible var to hold an error at the top you can do
if (quote instanceOf Error) ...
Though that won't work if something like a TypeError or Reference error is thrown. You can ensure it is a regular error though with
async function main() {
var quote = await getQuote().catch(err => {
console.error(err)
return new Error('Error getting quote')
})
if (quote instanceOf Error) return quote // get out of here or do whatever
console.log(quote)
}
My preference for this is wrapping everything in a big try-catch block where there's multiple promises being created can make it cumbersome to handle the error specifically to the promise that created it. With the alternative being multiple try-catch blocks which I find equally cumbersome
链接地址: http://www.djcxy.com/p/55388.html下一篇: 尝试/ catch异步/等待块