【问题标题】:jQuery promise everythingjQuery承诺一切
【发布时间】:2014-06-16 12:42:04
【问题描述】:

这种模式在 jQuery 或 javascript 中是否可行?:

$.when(function(){

    //I init many plugins here, some of them use ajax etc but I dont really control it
    //I only do something like $(div).somePlugin() here
    $("div").myPlugin()

}).done(function(){

   //and this part I want to be executed when all ajaxes and deferred stuff from when part is done
   //however I cannot go to every plugin and add something like deferred.resolve() etc.

});

例如,myPlugin 会有

$.fn.myPlugin = function(){
    $(this).load(someUrl);
};

(但我无法将 myPlugin 更改为它的一些外部代码。)

基本上我发生了很多事情,其中​​很多都使用async。功能。当所有这些async 时,我想执行一些功能。东西已经完成了,但我不能更改插件代码,所以我不能添加.resolve() 东西。

【问题讨论】:

  • 这取决于 - 如果它们只是常规方法,我看不出任何意义。
  • 我写的很多都是异步方法。
  • like - 你能发一个例子吗?
  • 添加了一些插件的例子
  • 投反对票的人,请记住,这是一个完全合理的问题,也是人们面临的一个非常普遍的问题。

标签: javascript jquery asynchronous promise jquery-deferred


【解决方案1】:

是的,这基本上就是.when 所做的!

// changes body html
var fisrtApi = $.get("http://something/foo").then(function(r){ $("body div").html(r); }); 
// inits some API for usage
var secondApi = somePromiseReturningFucntion();
// sets a plugin on top of a page    
var somePlugin = someOtherPromiseReturningFn();


$.when(firstApi,secondApi,somePlugin).done(function(r1, r2, r3){
     // all of them ready, results are the arguments
});

也可以pretty straightforward 将常规的非承诺返回 API 转换为承诺。

例如,让我们做$(document).ready(function(){

// returns a promise on the document being ready
function whenDocumentReady(){
    var d = $.Deferred();
    $(document).ready(function(){ d.resolve(); });
    return d.promise();
};

这会让你做什么:

$.when($.get("http://yourAPI"), whenDocumentReady()).done(function(apiResult,_){
    // access API here, the document is also ready.
});

例如 - 使用 jQuery twitter,库在完成获取数据时提供回调。你会答应它:

function getTweets(username, limit){
    var d = $.Deferred();
    $.twitter(username, limit , function(res){ d.resolve(res); });
    return d.promise();
}

这会让你做什么:

$.when(getTweets("someusername"),whenDocumentReady()).done(function(tweets){
       // document is ready here _and_ the twitter data is available,
       // you can access it in the `tweets` parameter
});

【讨论】:

  • 关键是你可以在这里访问你的异步对象。当您使用执行 ajax 之类的外部插件时,您无法访问该对象,通常它甚至不附加到任何变量。
  • @Kluska000 只要这些插件返回 jQuery 承诺以标记它们已完成,或者它们有一个回调方法,您可以将自己转换为承诺 - 您仍然可以这样做。请注意,在同步值上调用 $.when 也可以正常工作,并且会立即解决。
  • 正如我所写的那样,我有一个不返回任何内容的插件(就像大多数使用 ajax 的插件一样)。您是否能够多次使用(而不是修改)我的“插件”问题并等到他们的“隐藏”“.load”完成?
  • @Kluska000 如果它没有告诉你什么时候完成,那么你就无法知道它什么时候完成。大多数插件确实包含一些指示,但如果没有,您将无法修改插件或在 jQuery 的 AJAX 上设置全局挂钩(顺便说一下,它们可能会或可能不会使用)。
  • 好的,现在我确定你明白我的问题了。所以你说不可能。
【解决方案2】:

如果这就是你要找的,那么是的,这是完全可能的

$.when(sync(), async(), ajax()).done(function(s,a1, a2) {
   console.log( s + ' + ' + a1  + ' + ' + a2)     // outputs sync + async + ajax      
})

function sync() {
    return 'sync'   
}

function async() {
    var d = $.Deferred();

    setTimeout(function() {
        d.resolve('async')        
    }, 100)    

    return d;        
}

function ajax() {
    return $.post('http://jsfiddle.net/echo/html/', { html: 'ajax' })
}

【讨论】:

  • 如果某个制作您的“异步”插件功能的 John Knee 忘记了返回 d 或解决任何问题,因为他只希望他的 json url 中的内容跳转到他喜欢的 div 中,因为他不认识任何人是否需要等待它,或者那些日子他是一个糟糕的程序员,但他花了 2 个月的时间在一些很棒的插件上(有时它很常见)?顺便说一句,John 已经缩小了他插件的 js,因为他认为没有人需要修改它。
  • 您无法更改插件代码,但您可以将对这些插件的初始化调用包装在一个新的 Promise 中并在那里添加您的逻辑。
  • 但坦率地说,插件有多重要?如果需要,向他发送拉取请求,添加适当的承诺处理。
【解决方案3】:

我想这样做的唯一方法有点丑。

如果你不能使用 deferreds 和 resolve 方法,你别无选择,只能监听 dom 或 context 的变化(插件通常修改 DOM 或在 context 中创建新对象)。

然后你将不得不寻找$(myElt).hasClass('<class_created_and_applied_by_my_plugin>')从假到真,或类似的东西。

你必须为每个插件创建一个deferred,并将之前的测试包装在一个setInterval中来模拟一个监听器,最后解决deferred。

这样,您可以将所有的 deferred 放入一个 when 并确保在继续之前它们都已解决。

但这真的很丑,因为你必须为每个插件个性化测试。 而且我想,这肯定也会降低浏览器的速度。

【讨论】:

  • 在现代浏览器中,您可以使用变异观察器来代替,它不那么难看。但是,我相信绝大多数执行异步操作的插件都会为您提供一个挂钩,以便您了解这些操作何时完成。
  • 当然,我也是。如果没有......再拿一个! ;)
  • 关于变异观察者。假设插件只创建一个对象(提供特殊方法或属性,来自外部资源)并且不会更改 DOM...我不确定观察者会触发任何东西...
猜你喜欢
  • 2019-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-17
  • 2019-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多