如何在不可观察的函数中正确使用$ .deferred?

tru*_*ktr 5 javascript jquery jquery-deferred

比方说,我有两个函数,里面有随机代码,而且基于用户的系统(慢,中,或快),没有办法告诉这两个函数需要多长时间才能完成,所以使用的setTimeoutfunction2 function1完成尝试开火时不实用.

你怎么可以用jQuery.deferredfunction2后,才 function1不管时间要求是什么,并考虑到两个功能都100%无jQuery的,里面还没有jQuery代码的功能,因此完全未观察到的jQuery?最重要的是,这些函数可能包含jQuery方法.css(),这些方法没有时间关联,并且在旧计算机上运行速度较慢.

我如何确保function2不会同时执行,就像function1我这样称呼他们:

function1(); function2();
Run Code Online (Sandbox Code Playgroud)

$.deferred?除了那些有关的任何其他答案$.deferred也欢迎!

ADDED 3月20日: 如果function1()是一个lambda函数,根据用户输入,该函数可能有也可能没有异步调用,并且无法判断该函数将执行多少操作,该怎么办?它是一个函数,你不知道接下来会发生什么,但无论如何,你仍然希望function2只有完成lambda函数(f​​unction1)的所有操作才能执行,无论如何只要异步方面完成,它就需要很长时间.怎么能实现这一目标?

3月22日增加: 所以我想我做的唯一方法就是将匿名函数作为回调函数传递给异步函数,这些函数在完成后执行回调,或者创建事件监听器,这些函数将执行你想要的事件终于被触发了.

实际上没有任何方法可以在两个单独的行上执行异步调用并按顺序触发它们,而无需在包含所述函数的框架内手动构造机制(事件处理程序)来处理其操作的实际执行.

这些类型的机制的一个很好的例子是jQuery的.queue()方法和$.Defferred对象.

下面的答案以及阅读jQuery的API .queue()和使用$.Deferred有助于澄清这一点.

Tgr在下面给出了一个很好的例子,说明如何使用jQuery的$.Deferred对象创建自定义可链接函数,而自定义函数本身并不一定要在其中包含任何jQuery代码,这正是我想要的.

Tgr*_*Tgr 6

function first(deferred) {
    // do stuff
    deferred.resolve();
}
function second() {
    // do stuff
}

$.Deferred(first).then(second);
Run Code Online (Sandbox Code Playgroud)

但正如Tomalak指出的那样,这是不必要的,除非你做了一些非常棘手的事情first(比如利用网络工作者).

更新:

基本思想是,无论何时执行非直接的操作,都会创建一个Deferred对象,并返回该对象.(jQuery的AJAX调用已经这样做了.)然后你可以使用Deferred.then来延迟后续操作.

function first() {
    var deferred = $.Deferred();
    var callback = function() {
        deferred.resolve();
    }
    // do immediate stuff
    someAsyncOperation(callback);
    return deferred.promise(); // turns the Deferred into a Promise, which
                               // means that resolve() will not be accessible
}

function second() {
    // do stuff
}

first().then(second); // or: $.when(first).then(second)
Run Code Online (Sandbox Code Playgroud)

如果second也是异步操作,您可以使用$.when合并功能:

function second() {
    var anotherDeferred = $.Deferred();
    // do stuff with anotherDeferred
    return anotherDeferred.promise();
}

$.when(first(), second()).then(third); // third will run at the moment when 
                                   // both first and second are done
Run Code Online (Sandbox Code Playgroud)


Tom*_*lak 5

JavaScript本身不是异步的.它是单线程,同步的.

function1();
function2();
Run Code Online (Sandbox Code Playgroud)

除非它们包含异步调用,否则将逐个执行.在这种情况下,总会有一个你可以传递的回调(比如onSuccessXmlHttpRequest).将第二个功能放在那里.

说实话,即使它们包含异步位,它们也会严格执行.只是在函数的其余部分时,异步位可能还没有完成.


编辑你的jsFiddle示例,修复(见它):

function foo() {
  $('#foo')
  .html('<span>foo1</span>')
  .animate(
    {              /* properties */
      left: '100px' 
    },      
    360,           /* duration */
    'swing',       /* easing */
    function () {  /* "complete" callback */
      $('#foo').append('<span>foo2</span>');
      bar();
    } 
  );
}
Run Code Online (Sandbox Code Playgroud)

就像我说的.总会有一个你可以通过的回调.