【问题标题】:How to make the calling function wait until the called function finishes execution in jquery?如何让调用函数等到被调用函数在jquery中完成执行?
【发布时间】:2015-03-18 23:01:23
【问题描述】:

我有一个按钮,点击它会打开一个模式(dashboard_name),用户可以在其中输入一些值。根据他在该模态上单击提交后的值,我调用另一个函数,该函数打开另一个模态,用户在那里输入不同的值,最后当他在该模态上单击提交时,我调用一个 api 来验证一切是否正确。

现在,问题是当我单击第一个按钮打开模态时,执行不会等待函数从dashboard_name 模态然后从graph_name 模态获取数据。相反,它直接跳转到 api 函数调用,这是正确的,因为这就是 jQuery 的工作方式。但我想知道如何使用 deferred 和 promise 使这个执行串行。

单击第一个按钮时的功能。

$('#add_to_dash').click(function(e){
  dashboard_submit();
  graph_submit();      
});

此函数获取仪表板模式并尝试获取值。

function dashboard_submit(){
  //do something
}

dashboard_submit 函数成功后的此函数尝试获取图形模式的值

function graph_submit(){
  //do something
}

然后在提交表单时,我将其称为以下函数

<form name="form2" onsubmit="return isDashboardCorrect(dashboard_name);" method="post" action="{{ url_for('dashboards_new') }}">

功能

function isDashboardCorrect(dashboard_name) {
  var flag=0;
  $.ajax({
    async: false,
    type: 'GET',
    url: 'xyz.com/dashboard/'+dashboard_name,
    success: function(data) {
      //alert(data);
      //do something
   });
}

我希望所有这些都是顺序的,这现在不会发生,即当我单击第一个按钮时,它不会等待函数执行并直接调用 isdashboardcorrect() 函数。

我希望订单是 1.按钮点击 2.dashboard_submit() 3.graph_submit() 4. isdashboardcorrect() 连载。

我尝试了一些更简单的方法,例如

$('#add_to_dash').click(function(e){
  alert('addtodashstart');
  dashboard_submit().done(function(){
    alert('done');
  });


  alert('addtodashend');
});


function dashboard_submit()
{
  alert('dashboardsubmot');
  var dfd = new $.Deferred();
  $("#d_name_modal_div").modal({backdrop: false}).modal("show");
  $('#d_name_modal_submit').on('click', function(){
    dashboard_name=$('#dashboard_name').val();
    alert(dashboard_name);
    if(dashboard_name==null || dashboard_name.trim()=='')
    {
      alert('Dashboard name is mandatory.');
      return false;
    }
    else
    {
      dfd.resolve();
      return dfd.promise();
    }
  });
}

当我点击按钮时,我调用了dashboard_submit 函数。 但是这里也不需要等待

`$('#d_name_modal_submit').on('click', function(){  

this在上面的函数中执行,直接命中api函数。我做错了什么?`

小提琴示例:http://jsfiddle.net/LKP66/18/

【问题讨论】:

  • 在 Javascript 中,您不能“暂停”执行以等待异步操作完成。相反,您必须使用异步通知回调进行编码,以便在完成 Ajax 调用时完成您的操作。这是一种不同的编码方式,但一旦你学会了并不难。
  • 你能指出我正确的方向吗?如果您知道任何博客或示例?
  • 这么多代码,很少有人能读懂整件事。只需将第二个调用嵌套在第一个 ajax 调用的成功回调中或通过 jQuery.Deferred 同步这两个调用
  • 是否有任何关于延迟的简单教程,我很难理解这个概念,因为我对 jscript 很陌生。
  • 给我几分钟,我会给你一个模拟示例

标签: jquery promise jquery-deferred


【解决方案1】:

关于你的第二个问题: 你根本不明白我向你解释的内容,是吗?

done() 订阅回调在您解析延迟实例 dfd 时被调用。它几乎在你解决它的那一刻被调用。 因此,您将在收到数据后打开下一个对话框。

只需花 1-2 小时,尝试理解这个概念以及我向您解释的内容。你在那里做的编程很糟糕。

http://jsfiddle.net/qoytmgcj/2/

function dashboard_submit() {
     alert('Dashboard submit');
    var dfd = new $.Deferred();
    dashboard_name = 'ram';
     $("#d_name_modal_div").modal({
        backdrop: false
    });

    dfd.done(function(){
        var dn = $('#dashboard_name');
        dn.val('booooooo I recived the data now I can open the dialog');
        dn.text(dn.val());
        $("#d_name_modal_div").modal("show");
    });
    dfd.resolve();
    return dfd;
}

function wtf() {
    var dfd = $.Deferred();
    $('#d_name_modal_submit').on('click', function () {
        dashboard_name = $('#dashboard_name').val();
        alert(dashboard_name);
        if ( !$.trim(dashboard_name) ) {
            alert('Dashboard name is mandatory.');
            return false;
        } else {
            dfd.resolve();
            alert('success');
            return dfd;
        }
    });
} 


$('#add_to_dash').click(function (e) {

    alert('Add to dash start');
    dashboard_submit().done(function () {
        wtf();
    });
    alert('Add to dash end');
});

【讨论】:

  • 我希望我能更好地使用 javascript,但我正在努力。感谢@Kidwon 的帮助。
  • Kidwon,你真的是想通过 wtf 的点击处理程序来 return dfd 吗?
  • @Roamer-1888 没有将它返回到那里的位置,但那是小提琴中的@TommyT 代码,我只是对其进行了一些修改以进行演示。所以是的,返回是没有意义的,如果以后使用,在wtf 函数中这样做更有意义。返回dfd 的唯一原因是稍后在代码中解析它或订阅它的解析。如果不是不需要返回。
【解决方案2】:
  $('#add_to_dash').click(function(e) {

    $.when(dashboard_submit()).then(function(){
      graph_submit();
    });

  }); 

  function dashboard_submit() {
    var dfd = new $.Deferred();
    $.ajax({
      ....,
      ....,
      success: function (....) {
        dfd.resolve();
        /*some code...*/
      }
    });

    return dfd.promise();
  }

dfd 是一个对象,它可以有一些与$.ajax() 相同的结果,实际上它也返回延迟。什么是ajax结果? success, error, complete.... 你有他们的回调。与$.Deferred 的实例相同。但是,您可以控制结果是什么以及何时是解决、拒绝等。基于您的代码。如您所见,我已成功收到数据,我称它已成功解决dfd.resolve();。所以你可以认为.then().done() 等同于成功,都需要解决。区别在于then()dfd.promise().then()的方法而done()是dfd本身dfd.done()的方法

Ex.2

  $('#add_to_dash').click(function(e) {

    dashboard_submit().done(function(){
      graph_submit();
    });

    /* That is 
     dfd.done(function(){
       graph_submit();
     });         
     since dashboard_submit() returns dfd
    */

  }); 

  function dashboard_submit() {
    var dfd = new $.Deferred();
    $.ajax({
      ....,
      ....,
      success: function (....) {
        dfd.resolve();
        /*some code...*/
      }
    });

    return dfd;
  }

Ex.3

正如我提到的$.ajax() 返回$.Deferred 实例,因此无需显式创建一个,因此实际上不需要dfd,您已经提供了一个:

  $('#add_to_dash').click(function(e) {

    dashboard_submit().done(function(){
      graph_submit();
    });

  }); 

  function dashboard_submit() {
    return $.ajax({
      ....,
      ....,
      success: function (....) {

        /* The dfd that ajax returns is resolved on success by jQuery so no explicit instance creation is needed nor resolving*/
      }
    });
  } 

【讨论】:

  • 嘿。非常感谢@kidwon。你能解释一下吗,尤其是 deferred.resolve() 和 .done() 函数。谢谢。
  • 这不是一个特别好的设计模式。 $.ajax() 已经返回了一个承诺,因此您无需以任何方式创建自己的承诺。它也没有解决 OP 的问题,因为它仍然是一个承诺回调,告诉他们何时完成。而且,when() 不是 jQuery 中的函数,它是 $.when(),但也不需要它,因为您可以直接在返回的 promise 上使用 .then()。抱歉,但这不是如何做事的好例子。
  • @jfriend00 确实,但他没有线索让我们在这里,他应该有一个明确的例子。感谢$.when 欣赏它:)
  • @kidwon - 虽然 promise 对学习非常有用,但您真的不想以这种方式学习它们,因为这是错误的使用方式。这里有一些关于 Promise 反模式的阅读,What is the deferred antipattern and how do I avoid it?Promise anti-patternsPromise Anti-Patterns
  • $.when() 上,您根本不需要它。你可以做dashboard_submit().then(graph_submit)。在您的代码中,dashboard_submit 返回一个承诺,因此您可以直接在其上使用 .then()。不需要$.when()$.when() 当您有多个承诺并且希望在所有承诺都完成后进行回调时很有用。一个承诺是没有用的。
猜你喜欢
  • 2015-06-18
  • 2016-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-16
  • 2021-01-07
  • 1970-01-01
相关资源
最近更新 更多