为了账号安全,请及时绑定邮箱和手机立即绑定

使用异步/等待尝试/捕获块

使用异步/等待尝试/捕获块

呼啦一阵风 2019-11-12 10:55:42
我正在研究节点7异步/等待功能,并不断跨这样的代码绊脚function getQuote() {  let quote = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";  return quote;}async function main() {  try {    var quote = await getQuote();    console.log(quote);  } catch (error) {    console.error(error);  }}main();这似乎是使用async / await进行解析/拒绝或返回/抛出的唯一可能性,但是,v8不会在try / catch块中优化代码吗?有其他选择吗?
查看完整描述

3 回答

?
慕的地10843

TA贡献1785条经验 获得超8个赞

备择方案

替代方法:


async function main() {

  try {

    var quote = await getQuote();

    console.log(quote);

  } catch (error) {

    console.error(error);

  }

}

显式地使用诺言将是这样的:


function main() {

  getQuote().then((quote) => {

    console.log(quote);

  }).catch((error) => {

    console.error(error);

  });

}

或类似的东西,使用延续传递样式:


function main() {

  getQuote((error, quote) => {

    if (error) {

      console.error(error);

    } else {

      console.log(quote);

    }

  });

}

原始例子

您原始代码的作用是暂停执行,然后等待返回的承诺getQuote()解决。然后,它继续执行,并将返回的值写入var quote,如果承诺被解决,则将其打印出来;如果承诺被拒绝,则抛出异常并运行catch块,打印出错误。


您可以像第二个示例一样直接使用Promise API进行相同的操作。


性能

现在,为了表现。让我们测试一下!


我刚才写的代码- f1()给1作为返回值,f2()抛出1一个例外:


function f1() {

  return 1;

}


function f2() {

  throw 1;

}

现在,我们先用一百万次调用相同的代码f1():


var sum = 0;

for (var i = 0; i < 1e6; i++) {

  try {

    sum += f1();

  } catch (e) {

    sum += e;

  }

}

console.log(sum);

然后让我们更改f1()为f2():


var sum = 0;

for (var i = 0; i < 1e6; i++) {

  try {

    sum += f2();

  } catch (e) {

    sum += e;

  }

}

console.log(sum);

这是我得到的结果f1:


$ time node throw-test.js 

1000000


real    0m0.073s

user    0m0.070s

sys     0m0.004s

这是我得到的f2:


$ time node throw-test.js 

1000000


real    0m0.632s

user    0m0.629s

sys     0m0.004s

似乎您可以在一个单线程进程中每秒执行200万次抛出。如果您要做的还不止这些,那么您可能需要担心。


摘要

我不会担心Node中的问题。如果像这样的事情被广泛使用,那么它最终将由V8或SpiderMonkey或Chakra团队进行优化,并且每个人都会效仿–这并不是说它没有作为一个原则进行优化,这不是问题。


即使未进行优化,我仍然会争辩说,如果您要在Node中使CPU发挥最大作用,那么您可能应该使用C语言编写数字运算法则-这就是本机插件的用途。或者也许像node.native这样的事情比Node.js更适合这份工作。


我想知道什么是用例,需要抛出这么多异常。通常,抛出异常而不是返回值是一个异常。


查看完整回答
反对 回复 2019-11-12
?
12345678_0001

TA贡献1802条经验 获得超5个赞

async function main() {

  var getQuoteError

  var quote = await getQuote().catch(err => { getQuoteError = err }


  if (getQuoteError) return console.error(err)


  console.log(quote)

}

另外,您也可以声明一个变量而不是在顶部声明错误,而不是声明


if (quote instanceof Error) {

  // ...

}

虽然如果抛出TypeError或Reference错误之类的东西,那将不起作用。您可以通过以下方式确保它是常规错误


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)

}

我的偏好是将所有内容包装在一个大的try-catch块中,在该块中创建了多个promise,这使得处理错误(特别是针对创建它的promise)变得很麻烦。另一种选择是多个try-catch块,我觉得同样麻烦


查看完整回答
反对 回复 2019-11-12
?
米琪卡哇伊

TA贡献1998条经验 获得超6个赞

与Golang中的错误处理类似的替代方法

因为async / await在幕后使用promises,所以您可以编写一个小的实用程序函数,如下所示:


export function catchEm(promise) {

  return promise.then(data => [null, data])

    .catch(err => [err]);

}

然后,在需要捕获一些错误时将其导入,并包装异步函数,该函数将返回一个Promise。


import catchEm from 'utility';


async performAsyncWork() {

  const [err, data] = await catchEm(asyncFunction(arg1, arg2));

  if (err) {

    // handle errors

  } else {

    // use data

  }

}


查看完整回答
反对 回复 2019-11-12
  • 3 回答
  • 0 关注
  • 524 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信