jQuery$.延迟固有的问题(jQuery 1.x/2.x)

jQuery$.延迟固有的问题(jQuery 1.x/2.x)

有一篇关于jQuery延迟对象失败的非常详尽的文章:你错过了承诺的要点..在这篇文章中,多梅尼奇强调了jQuery承诺与其他承诺相比的一些缺点,包括Q、RSVP.js和ES6承诺。

我离开了多梅尼奇的文章,觉得jQuery承诺在概念上有一个固有的缺陷。我想举例说明这个概念。

我认为jQuery实现有两个关注点:

1..then方法是不可链接的。

换句话说

promise.then(a).then(b)

jQuery将调用a然后bpromise都实现了。

.then在其他承诺库中返回一个新的承诺,它们的等效值是:

promise.then(a)promise.then(b)

2.jQuery中出现异常处理。

另一个问题似乎是异常处理,即:

try {
  promise.then(a)} catch (e) {}

在Q中相当于:

try {
  promise.then(a).done()} catch (e) {
   // .done() re-throws any exceptions from a}

在jQuery中,当a捕获块失败。在另一个承诺中,任何例外a会被带到.done.catch或者其他异步捕获。如果所有的承诺API调用都没有捕获异常,那么它就消失了(因此,使用.done若要释放任何未处理的异常,请执行以下操作。

 

上面的问题是否涵盖了jQuery承诺实现的问题,还是我误解或忽略了一些问题?


编辑此问题涉及jQuery<3.0;jQuery3.0alphajQuery是答应/A+兼容的。


慕容森
浏览 383回答 3
3回答

慕仙森

jQuery3.0修复了下面概述的问题。这是真正的承诺/A+符合。是的,jQuery承诺存在严重的固有问题。尽管如此,由于这篇文章是写的,jQuery做出了很大的努力,希望成为更多的承诺/Aplus抱怨,现在他们有了一种.然后链接的方法。所以即使在jQuery中returnsPromise().then(a).then(b)用于承诺返回函数a和b将按预期工作,在继续前进之前展开返回值。如图所示小提琴:function&nbsp;timeout(){ &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;d&nbsp;=&nbsp;$.Deferred(); &nbsp;&nbsp;&nbsp;&nbsp;setTimeout(function(){&nbsp;d.resolve();&nbsp;},1000); &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;d.promise();}timeout().then(function(){ &nbsp;&nbsp;&nbsp;document.body.innerHTML&nbsp;=&nbsp;"First"; &nbsp;&nbsp;&nbsp;return&nbsp;timeout();}).then(function(){ &nbsp;&nbsp;&nbsp;document.body.innerHTML&nbsp;+=&nbsp;"<br&nbsp;/>Second"; &nbsp;&nbsp;&nbsp;return&nbsp;timeout();}).then(function(){ &nbsp;&nbsp;&nbsp;document.body.innerHTML&nbsp;+=&nbsp;"<br&nbsp;/>Third"; &nbsp;&nbsp;&nbsp;return&nbsp;timeout();});然而,这两个巨量jQuery的问题是错误处理和意外执行顺序。错误处理与CATCH不同,即使您解决了jQuery承诺,也无法将其标记为“已处理”。这使得jQuery中的拒绝固有地中断,并且非常难以使用,这与同步没有什么相似之处。try/catch.你能猜到这里有什么日志吗?小提琴)timeout().then(function(){ &nbsp;&nbsp;&nbsp;throw&nbsp;new&nbsp;Error("Boo");}).then(function(){ &nbsp;&nbsp;&nbsp;console.log("Hello&nbsp;World");},function(){ &nbsp;&nbsp;&nbsp;&nbsp;console.log("In&nbsp;Error&nbsp;Handler");&nbsp;&nbsp;&nbsp;}).then(function(){ &nbsp;&nbsp;&nbsp;console.log("This&nbsp;should&nbsp;have&nbsp;run");}).fail(function(){ &nbsp;&nbsp;&nbsp;console.log("But&nbsp;this&nbsp;does&nbsp;instead");&nbsp;});如果你猜到"uncaught Error: boo"你是对的。jQuery的承诺是不扔保险柜..它们将不允许您处理任何抛出的错误,而不是承诺/Aplus承诺。拒绝安全怎么办?小提琴)timeout().then(function(){ &nbsp;&nbsp;&nbsp;var&nbsp;d&nbsp;=&nbsp;$.Deferred();&nbsp;d.reject(); &nbsp;&nbsp;&nbsp;return&nbsp;d;}).then(function(){ &nbsp;&nbsp;&nbsp;console.log("Hello&nbsp;World");},function(){ &nbsp;&nbsp;&nbsp;&nbsp;console.log("In&nbsp;Error&nbsp;Handler");&nbsp;&nbsp;&nbsp;}).then(function(){ &nbsp;&nbsp;&nbsp;console.log("This&nbsp;should&nbsp;have&nbsp;run");}).fail(function(){ &nbsp;&nbsp;&nbsp;console.log("But&nbsp;this&nbsp;does&nbsp;instead");&nbsp;});以下日志"In Error Handler" "But this does instead"-根本无法处理jQuery承诺的拒绝。这与您所期望的流程不同:try{ &nbsp;&nbsp;&nbsp;throw&nbsp;new&nbsp;Error("Hello&nbsp;World");}&nbsp;catch(e){ &nbsp;&nbsp;&nbsp;console.log("In&nbsp;Error&nbsp;handler");}console.log("This&nbsp;should&nbsp;have&nbsp;run");这就是承诺/A+库(如Bluebird和Q)的流程,以及您期望的有用性。这是巨量抛出安全是承诺的一个重要卖点。这是蓝鸟在这种情况下动作正确.执行命令jQuery将执行传递的函数。立马如果底层承诺已经解决,而不是推迟它,那么代码的行为将有所不同,这取决于我们向拒绝的处理程序附加的承诺是否已经解决。这是有效的释放扎尔戈会引起一些最痛苦的虫子。这就产生了一些最难调试的bug。如果我们查看以下代码:小提琴)function&nbsp;timeout(){ &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;d&nbsp;=&nbsp;$.Deferred(); &nbsp;&nbsp;&nbsp;&nbsp;setTimeout(function(){&nbsp;d.resolve();&nbsp;},1000); &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;d.promise();}console.log("This");var&nbsp;p&nbsp;=&nbsp;timeout();p.then(function(){ &nbsp;&nbsp;&nbsp;console.log("expected&nbsp;from&nbsp;an&nbsp;async&nbsp;api.");});console.log("is");setTimeout(function(){ &nbsp;&nbsp;&nbsp;&nbsp;console.log("He"); &nbsp;&nbsp;&nbsp;&nbsp;p.then(function(){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.log("̟̺̜̙͉Z̤̲̙̙͎̥̝A͎̣͔̙͘L̥̻̗̳̻̳̳͢G͉̖̯͓̞̩̦O̹̹̺!̙͈͎̞̬&nbsp;*"); &nbsp;&nbsp;&nbsp;&nbsp;}); &nbsp;&nbsp;&nbsp;&nbsp;console.log("Comes");},2000);我们可以观察到,哦,如此危险的行为,setTimeout等待原始超时结束,因此jQuery切换其执行顺序,因为.。谁喜欢不会导致堆栈溢出的确定性API?这就是为什么允诺/A+规范要求承诺总是被推迟到事件循环的下一次执行。旁注值得一提的是,更新更强的承诺库,如蓝鸟库(以及实验时)不需要.done在链的末尾,就像Q一样,因为它们自己发现了未处理的拒绝,它们也比jQuery承诺或Q承诺要快得多。

翻翻过去那场雪

这几乎不是一个黑暗的巫毒把戏,没有必要去寻找它的来源。自从jQuery 1.8发布以来,文档已经读过了"these filter functions can return a new value to be passed along to the promise's .done() or .fail() callbacks, or they can return another observable object (Deferred, Promise, etc) which will pass its resolved / rejected status and values to the promise's callbacks"..因此,并不是一个“大问题”,如果你活着,实际上根本不是一个问题
打开App,查看更多内容
随时随地看视频慕课网APP