答:是的,这个无需看源码,仅看api也很清楚,jQuery.Deferred.promise()没有实现promises/A+。例如jQuery增加了done、fail、progress等函数,这三个函数都不是promises/A+模型标准的函数名,但是却近似实现了promises/A+的概念模型。同时,promises/A+里面有catch函数,但是jQuery却没有实现,主要原因是catch是早期的ie浏览器中的键字,因此使用了fail代替。done、progress是jQuery根据自身需要进行的扩展。
jQuery.Deferred.promise和promises/A+还有一个重要区别,就是对异常的处理。实例代码如下:
d = new Promise((resolve)=>{resolve()}) d.then(()=>{throw "error"}) .catch((e)=>{alert(e)})标准的promise弹出error字样的alert框。
再换位jQuery.Deferred.promise测试:
$.Deferred().resolve().then(()=>{throw "error"}).fail((e)=>{alert(e)})结果直接报错,并没有弹出alret框。
源码中jQuery没有对回调的调用做异常处理,所以无法把回调的异常自动返回rejected的promise。这一点不同使得jQuery.Deferred的异常处理非常不灵活,需要手动进行。修改为:
$.Deferred() .resolve() .then(()=>{ try{ throw "error" }catch(e){ return $.Deferred().reject(e); } }).fail((e)=>{ alert(e) })这样才能弹出error字样的alert框。
提问:jQuery.Deferred.promise()能和浏览器的promise相互调用吗?答:当然不能直接调用,需要做转换,转换代码这里就不演示了。不能直接调用的原因是jQuery.Deferred.promise没有实现promises/A+。但是这只是一部分原因,最大的原因还是历史问题,jQuery2.0的时候,浏览器的promise模型还没有建立,所以根本不可能去考虑与浏览器的promise相互调用的问题。
提问:如果想要jQuery.Deferred.promise()能和浏览器的promise直接调用,jQuery.Deferred.promise需要做哪些改善?答:首先起码要对promises/A+做到完整实现,去掉jQuery个性化的东西,如xxxWith调用、Deferred代替promise、去除done等不规范的函数命名、能够catch到异常等。所以,在jQuery3中jQuery.Deferred都做了不可升级式的调整,新的jQuery.Deferred.promise完全实现了promises/A+规范,并且可以调用浏览器的promise相互调用。