关于 Promise 的 3 个事实
封面图片由 Carmella Fernando 在 Flickr 上发布,由我裁剪
Promises 是 JavaScript 开发者们新发现的挚爱,但我经常看到这样的话:“它们不就是更复杂的回调吗?!”。所以,在最近看了这么多关于 Promises 的帖子后,我想提出我的看法,希望能帮助大家写出更好的代码。
1. Promise 并不关心你何时需要它们的数据
承诺的一个非常好的特性使它们优于回调,那就是它们并不关心你何时使用 添加回调then
。
你可以编写这样的代码,它就可以正常工作:
const wait = ms => new Promise(r => setTimeout(r, ms));
const waitTenMilliseconds = wait(10);
setTimeout(() =>
waitTenMilliseconds.then(() => console.log("Hello!"))
, 1000);
第一个承诺waitTenMilliseconds
将在添加回调的超时之前解决,但仍会调用回调。
提示:有时,Promise 的实现在何时调用会有所不同。有些 Promise 会将所有回调放在事件循环的末尾,而有些 Promise 会在 Promise 已解析或同步计算后立即调用。
2. 承诺掩盖其他承诺
通常,当您阅读基于承诺的代码时,您可以立即发现某人不知道这一点,但这是一个非常好的功能,可以让您将已有的值与需要异步计算或获取的值混合在一起。
then
具有单子行为,它会检查回调中返回的内容,如果是另一个 Promise,它会等待它解析,然后从中解压值并将其放入下一个回调中。如果只是一个普通值,它会立即将其放入下一个回调中。
Promise.resolve("ID_123")
.then(userId => fetch("/users/" + userId)) // returns a promise
.then(response => response.json()) // returns a promise
.then(json => `${json.firstName} ${json.lastName}`) // returns a string
.then(name => console.log(name)) // returns undefined
正如我所说,混合也是允许的!
const myData = [
0,
123,
fetch("/number/456").text(),
fetch("/number/789").text(),
999
];
Promise.all(myData)
.then(numbers => console.log(numbers.join(", ")));
该myData
数组包含值和 Promise。静态all
方法Promise
会检查每个值,将其添加到一个新数组中,并等待 Promise 解析后再添加它们。这使得下一个then
回调可以获取相同大小的数组,但数组中所有 Promise 解析后,所有 Promise 都会被替换为它们的值。
3. Promise 把错误当早餐
大多数情况下,当你的 Promise 内部出现错误时,你会收到一个未处理的 Promise 拒绝错误,但更常见的情况是,你最终得到的是没有抛出任何异常,你的代码根本就什么也不做,甚至没有显示任何错误。有时是因为库返回的 Promise 还没有实现reject
对错误的调用。
对于异步函数来说,情况会更糟,因为你再也看不到 Promise 了。你async
在函数前面加上一个,所有错误都消失了,因为你的函数现在被包裹在 Promise 里,并吞掉了你的错误。
catch
因此,使用承诺或异步函数try-catch
检查错误非常重要。
结论
Promises 是 JavaScript 的一个很棒的补充,但它并非没有代价。我认为它们能让你写出比普通回调更结构化的代码,但就像所有抽象概念一样,你必须理解它们,否则它们会给你带来麻烦。
50. 文章
我 2017 年的新年愿望是每周写一篇文章,我几乎实现了。
有时我生病了或者不想写东西,但您的评论和点赞让我坚持了下来。
谢谢你!
另外,我要感谢dev.to的创建者,他们让开发人员可以轻松编写!
最近我看到开发领域的 MVP 纷纷涌向该平台,因此 2018 年该平台将如何变化将会很有趣!
鏂囩珷鏉ユ簮锛�https://dev.to/kayis/3-facts-about-promises-215c