1. 简明整洁
看看我们并没有写多少代码! 即使在上面的例子中,也很清楚明了,我们节省了大量的代码。 我们不必编写.then,不必创建一个匿名函数来处理响应,不必将命名数据传递给我们不需要使用的变量。
我们也避免了嵌套代码。 这些小的优点叠加起来,这在下面的代码示例中将会变得更加明显。
2. 错误处理
Async/await 使得用同一种构造(古老但好用的 try/catch ) 处理同步和异步错误成为可能。在下面的 promises 示例中,因为错误发生在 promises 中,try/catch 将不会处理 JSON.parse 失败的情况。
我们需要在 promise 中调用 .catch ,并复制我们的错误处理代码,这将可能比你的生产就绪代码中的 console.log 更复杂。
现在看看相同的 async/await 调用代码。catch 模块现在可以处理 parsing 错误了。
3. Conditionals
设想一下像下面的代码,它会获取一些数据,并决定是否应该返回该数据,或者根据数据中的某些值获取更多信息。
仅仅是看着这些就让你头疼了。很容易迷失在所有嵌套中(6级),大括号和返回语句中,而这些仅仅是在将最终结果传递给主 promise 中所需要的。
当用 async/await 重写时,此示例变得更易于阅读。
4. 中间值
你可能会遇到这样一种情形,先调用 promise1,其返回值将用于调用 promise2,之后再调用 promise3 的时候需要用到前面两个返回值。那么代码可能写成这样
如果 promise3 不需要 value1,那么 Promise 就不需要嵌套这么深。如果你是不喜欢深层嵌套的人,可以使用 Promise.all 来封装 value1 和 value2 来避免深层嵌套,像这样:
这种方法会牺牲语义,降低可读性。把 value1 和 value2 放在一个数组里,除了避免嵌套 Promise,找不到其它任何理由。
使用 async/await 来完成同样的逻辑就非常简单。它会让你怀疑之前为简化 Promise 而进行的所有艰苦奋斗。
5. 错误栈
想象一下,某段链式调用的代码中使用了多个 Promise,其中的某个位置会抛出一个错误。
从 Promise 链中返回的错误栈找不到一点错误发生位置的线索。更糟糕的是,它会产生误导;它的包含的唯一的函数名是 callPromise,但它与这个错误无关 (文件和行号仍然有用)。
不过,async/await 产生的错误栈会指向包含错误的函数
在本地环境中开发并使用编辑器编辑文件的时候这并不是多大的好处,不过如果你想从生产服务器获取错误日志,这就非常有用了。
这种情况下,知道错误发生在 makeRequest 中总比不知道它在若干 then 调用的哪一个里面好吧 ...
6. 调试
最后一点并非最不起眼,async/await 的杀手锏是易于调试。调试 Promise 总会有 2 点特别痛苦
1. 不能为箭头函数表达式设置断点 (没有函数体)。
(找个地方设置断点试试)
2. 如果在 .then 块中设置断点,然后使用调试快捷方式,比如跳过,调试器并不会移到下一个 .then 中,因为它是在代码中“步进”。
有了 async/await,你就不再需要这么多箭头函数,你可以在 await 调用中步进,就像普通的同步代码调用那样。