q.allsettled_Promise.allSettled()和Promise.any()有什么问题❓

q.allsettled

我最近阅读了v8博客中的Promise组合器文章 。 它涉及Promise API中即将推出的两个方法: Promise.allSettled()Promise.any() 。 我感到沮丧。 在我看来,这些方法的设计与当前的Promise API不一致。 让我在下面分享我的意见。

承诺全部解决

根据文章:

Promise.allSettled会在所有输入承诺均已兑现时向您发出信号,这意味着它们已实现或被拒绝。

用例是发送几个API调用并等待所有完成:

const promises = [
  fetch( '/api-call-1' ),
  fetch( '/api-call-2' ),
  fetch( '/api-call-3' ),
];

await Promise .allSettled(promises);

removeLoadingIndicator();

当然,这很有用。 但是可以使用.map()Promise.all()轻松解决此任务。 变化很小:

const promises = [
  fetch( '/api-call-1' ),
  fetch( '/api-call-2' ),
  fetch( '/api-call-3' ),
].map( p => p.catch( e => e)); // <-- the only change

await Promise .all(promises);

removeLoadingIndicator();

是否值得实施可以用几行代码解决的新核心方法? 对我来说,这是一个库功能,而不是核心API方法。

但是更重要的是Promise.allSettled带来了额外的抽象级别。 与Promise.all不同,它使用包装对象数组{status,reason}代替纯Promise值来实现。 作为开发人员,我不喜欢它。 我希望名称类似.all()/。allSettled()的方法的行为类似。 但是他们没有。

而且,带有Promise.allSettled的代码鼓励后期错误处理。 错误应该从最终结果中滤除,而不是从传统的catch块中滤除。 反过来,这具有以下缺点:

  • 错误发生时不会立即进行处理。 如果发生几个相关的错误,您可能不知道哪个是原始错误。 并且日志将包含不正确的时间戳。
  • 如果至少一个诺言永远悬而未决,则不会处理错误。

使用当前的Promise.all,您可以避免此类情况。

无极

承诺之一兑现后,Promise.any就会向您发出信号。

换句话说, Promise.anyPromise.race ,它会忽略拒绝。

用例是检查多个端点并从第一个成功的端点获取数据:

const promises = [
  fetch( '/endpoint-a' ).then( () => 'a' ),
  fetch( '/endpoint-b' ).then( () => 'b' ),
  fetch( '/endpoint-c' ).then( () => 'c' ),
];
try {
  const first = await Promise .any(promises);
} catch (error) {
  // All of the promises were rejected.
  console .log(error);
}

我同意有时它可能有用。 但是多久一次? 您在多少个项目中使用了“ 对相同数据的相同端点发出多个并行请求”模式 ? 随时分享评论。 但是从我的角度来看-并不经常。 对于社区而言,获取蓝鸟的 Promise.each()Promise.delay()的本地实现不是更有用吗?

此外, Promise.any引入了一种新的错误类型— AggregateError 。 如果所有承诺均被拒绝,则此类错误包含其他错误的链接。 另一种错误处理方法! 它不同于Promise.allSettled ,后者从成功结果中提取错误。 它也不同于Promise.all / Promise.race ,后者仅通过Error实例拒绝。 如果每个新的Promise API方法都将引入新的错误处理方式,那么JavaScript将如何? 尽管该提案尚处于初期阶段,但我对该方向感到担忧。

基于当前的Promise API, Promise.any的实现有些棘手,但实际上有两行代码

const reverse = p => new Promise ( ( resolve, reject ) => Promise .resolve(p).then(reject, resolve));
Promise .any = arr => reverse( Promise .all(arr.map(reverse)));

也许将其保存在图书馆?

前后矛盾

为什么Promise.allPromise.race如此漂亮?

因为它们的行为非常一致,并且与通常的诺言相似:只需执行一个值即可完成,而仅执行错误即可拒绝。 没有包装的值,没有累积的错误,没有额外的复杂性。

为什么Promise.allSettledPromise.any对我这么奇怪?

Promise.allSettled使用对象数组来实现,该对象数组具有包装潜在承诺值的状态和原因。 拒绝...永远。

Promise.any满足单个值,但忽略中间拒绝。 仅当所有诺言都被拒绝时,它才会以累积原因包装所有根本原因来拒绝。

这些新方法真的很难让我想到。 由于它们与当前的Promise API完全不同。

我想在2020年出现一个受欢迎的工作面试问题:

这四种方法有什么区别?

  • Promise.all()
  • Promise.allSettled()
  • Promise.race()
  • Promise.any()

尽管这是一个很酷的问题,但我认为核心API不应鼓励这种复杂性。

命名

我也对命名感到失望。 四种行为稍有不同的方法应使用非常清晰的名称。 否则,每次在代码中遇到MDN时,我都必须重新检查MDN 。 从Promise.any建议中:

它清楚地描述了它的作用

让我不同意。 对我来说Promise.any的名称令人困惑:

  • 如果有任何诺言,诺言就会实现吗? 是的
  • 如果任何承诺被拒绝,它会拒绝吗? 不行
  • 如果有任何诺言,它会解决吗? 这要看情况
  • 它与Promise.race有何不同? ..

我认为,每个方法的名称都应在方法实现时明确定义条件。 我建议以下命名约定:

Promise .all        -> Promise .allFulfilled
Promise .allSettled -> Promise .allSettled
Promise .race       -> Promise .oneSettled
Promise .any        -> Promise .oneFulfilled

它反映了承诺状态的四种可能组合。 它解释了为什么在建议中将这些方法称为组合器

当然,这样的重命名是不可能的,因为Promise.allPromise.race已经登陆并在许多应用程序中使用了。 但是对于具有某些命名策略的新方法将非常有帮助。

我已经在GitHub上的Promise.any提案存储库中打开问题 ,欢迎您分享您的想法。

吞下拒绝

总的来说,我不受非扔掉的“吞咽”拒绝概念的启发。 实际上,新的Promise API提供了一种方法来静默忽略代码中的错误:

  • Promise.allSettled从不拒绝。
  • Promise.any仅在所有承诺均被拒绝的情况下拒绝。

当前没有其他核心JavaScript API可以做到这一点。 忽略错误的唯一方法-手动将其包装到带有空主体的try..catch / .catch()中 。 并发表评论,为什么在这里忽略错误,否则eslint会警告您

我认为核心API应该公开所有错误 。 是否处理错误始终是开发人员的决定。 对于其他开发人员来说,阅读代码应该是明确的。 试想一下,由于吞咽拒绝的使用不正确,调试将花费多少小时! 尤其是在处理第三方代码时-当某些操作不起作用并且没有引发任何错误时。

结论

我在每个工作日都使用诺言。 和许多其他开发人员一样。 我喜欢JavaScript的异步特性。 拥有清晰直观的API,可让我更快地解决任务并提高工作效率。 这就是为什么我认为应该非常谨慎地对待和更改Promise API的原因。

感谢您的阅读,欢迎发表评论。

翻译自: https://hackernoon.com/whats-wrong-with-promiseallsettled-and-promiseany-yfib64aiv

q.allsettled

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值