gpt4 book ai didi

jquery - jQuery $.Deferred (jQuery 1.x/2.x) 固有的问题

转载 作者:行者123 更新时间:2023-12-03 21:27:48 24 4
gpt4 key购买 nike

@Domenic 有一篇关于 jQuery 延迟对象的缺点的非常详尽的文章:You're missing the Point of Promises 。在其中,Domenic 强调了 jQuery promise 与其他 promise 相比的一些缺陷,包括 Q 、when.js、RSVP.js 和 ES6 promise 。

读完 Domenic 的文章后,我感觉 jQuery Promise 在概念上有一个固有的缺陷。我正在尝试举例说明这个概念。

我认为 jQuery 实现有两个问题:

1。 .then 方法不可链接

换句话说

promise.then(a).then(b)

promise 实现时,jQuery 将调用 a,然后调用 b

由于 .then 在其他 Promise 库中返回一个新的 Promise,它们的等价物是:

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 无法捕获 block 时,异常会抛出并冒泡。在另一个 Promise 中,a 中的任何异常都将被传递到 .done.catch 或其他异步捕获。如果没有一个 Promise API 调用捕获异常,它就会消失(因此 Q 最佳实践是使用 .done 来释放任何未处理的异常)。

 

上述问题是否涵盖了 jQuery promise 实现的问题,还是我误解或遗漏了问题?

<小时/>

编辑这个问题与 jQuery < 3.0 有关;截至jQuery 3.0 alpha jQuery 符合 Promises/A+ 标准。

最佳答案

更新:jQuery 3.0 已修复下列问题。它真正符合 Promises/A+ 标准。

是的,jQuery Promise 存在严重且固有的问题。

也就是说,自从这篇文章写完以来,jQuery 做出了巨大的努力来更好地满足 Promises/Aplus 的要求,并且他们现在有了一个 .then 链接方法。

因此,即使在 jQuery returnsPromise().then(a).then(b) 中,promise 返回函数 ab 也可以工作正如预期的那样,在继续前进之前解开返回值。如本fiddle所示:

function timeout(){
var d = $.Deferred();
setTimeout(function(){ d.resolve(); },1000);
return d.promise();
}

timeout().then(function(){
document.body.innerHTML = "First";
return timeout();
}).then(function(){
document.body.innerHTML += "<br />Second";
return timeout();
}).then(function(){
document.body.innerHTML += "<br />Third";
return timeout();
});

但是,jQuery 的两个巨大问题是错误处理和意外的执行顺序。

错误处理

与 catch 不同,即使您解决了它,也无法将被拒绝的 jQuery Promise 标记为“已处理”。这使得 jQuery 中的拒绝本质上被破坏并且非常难以使用,与同步 try/catch 完全不同。

你能猜出这里记录了什么吗? (fiddle)

timeout().then(function(){
throw new Error("Boo");
}).then(function(){
console.log("Hello World");
},function(){
console.log("In Error Handler");
}).then(function(){
console.log("This should have run");
}).fail(function(){
console.log("But this does instead");
});

如果您猜到“ Uncaught Error :boo”,那么您是对的。 jQuery 的 promise 是不安全。与 Promises/Aplus Promise 不同,它们不会让您处理任何抛出的错误。拒绝安全怎么样? (fiddle)

timeout().then(function(){
var d = $.Deferred(); d.reject();
return d;
}).then(function(){
console.log("Hello World");
},function(){
console.log("In Error Handler");
}).then(function(){
console.log("This should have run");
}).fail(function(){
console.log("But this does instead");
});

以下日志“在错误处理程序中”“但这确实是” - 根本没有办法处理 jQuery promise 拒绝。这与您期望的流程不同:

try{
throw new Error("Hello World");
} catch(e){
console.log("In Error handler");
}
console.log("This should have run");

这是您使用 Bluebird 和 Q 等 Promises/A+ 库获得的流程,以及您期望的有用性。这是巨大,并且 throw 安全性是 Promise 的一大卖点。这是Bluebird acting correctly in this case .

执行顺序

如果底层 Promise 已经解析,jQuery 将立即执行传递的函数,而不是推迟它,因此代码的行为会有所不同,具体取决于我们附加处理程序拒绝的 Promise 是否已经解析。这实际上是releasing Zalgo并可能导致一些最痛苦的错误。这会产生一些最难调试的错误。

如果我们看下面的代码:( fiddle )

function timeout(){
var d = $.Deferred();
setTimeout(function(){ d.resolve(); },1000);
return d.promise();
}
console.log("This");
var p = timeout();
p.then(function(){
console.log("expected from an async api.");
});
console.log("is");

setTimeout(function(){
console.log("He");
p.then(function(){
console.log("̟̺̜̙͉Z̤̲̙̙͎̥̝A͎̣͔̙͘L̥̻̗̳̻̳̳͢G͉̖̯͓̞̩̦O̹̹̺!̙͈͎̞̬ *");
});
console.log("Comes");
},2000);

我们可以观察到,哦,如此危险的行为,setTimeout 等待原始超时结束,因此 jQuery 切换其执行顺序,因为......谁喜欢不会导致堆栈溢出的确定性 API ?这就是 Promises/A+ 规范要求 Promises 始终推迟到事件循环的下一次执行的原因。

旁注

值得一提的是,像 Bluebird 这样更新、更强大的 Promise 库(以及实验性的 When)不需要像 Q 那样在链的末尾处 .done ,因为它们自己找出未处理的拒绝,它们是也比 jQuery Promise 或 Q Promise 快得多。

关于jquery - jQuery $.Deferred (jQuery 1.x/2.x) 固有的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23744612/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com