【问题标题】:function sequence not getting executed as expected when dealing with jquery promise处理 jquery promise 时函数序列未按预期执行
【发布时间】:2015-08-07 19:48:11
【问题描述】:

我有一些代码,我想在函数完成后执行这些代码,单击按钮将调用这组步骤和函数。以下是我的代码:

$scope.activetab = function (tabname, $event) {
   $.when(function () {
        showLoader();
        alert('done');
   }).done(function () {
        alert('next');
        if (tabname == 'General')
             $scope.GeneralAct = true;
        else if (tabname == 'Contact Information')
             $scope.ContactAct = true;
        else if (tabname == 'Position/Hierarchy')
             $scope.PositionAct = true;
        else if (tabname == 'Ids and Program Access')
             $scope.IdsAct = true;
        else if (tabname == 'Equipment')
             $scope.EquipmentAct = true;
        else if (tabname == 'Licensing')
            $scope.LicensingAct = true;
    });
};

我的showLoader函数如下:

function showLoader() {
    var dfd = $.Deferred();
    $('body').append('<div class="loader"></div>');
    dfd.promise();
}

但是这里alert('next') 先被执行,然后alert('done') 被执行。这里的实际问题是什么?我不太确定承诺在这里的工作方式!谁能告诉我如何纠正这个问题?

【问题讨论】:

    标签: javascript jquery angularjs promise


    【解决方案1】:

    $.when() 无法正常工作,因为您没有从传递它的函数返回承诺。但是,showLoader() 不是异步的,所以根本不需要使用 Promise。

    由于您的代码中没有显示异步操作,您可以像这样同步编程:

    $scope.activetab = function (tabname, $event) {
            showLoader();
            if (tabname == 'General')
                 $scope.GeneralAct = true;
            else if (tabname == 'Contact Information')
                 $scope.ContactAct = true;
            else if (tabname == 'Position/Hierarchy')
                 $scope.PositionAct = true;
            else if (tabname == 'Ids and Program Access')
                 $scope.IdsAct = true;
            else if (tabname == 'Equipment')
                 $scope.EquipmentAct = true;
            else if (tabname == 'Licensing')
                $scope.LicensingAct = true;
    };
    
    function showLoader() {
        // this is a synchronous operation, so no need for promises here
        $('body').append('<div class="loader"></div>');
    }
    

    如果showLoader() 内部有异步操作,那么要将它与$.when() 一起使用,您必须做三件您目前没有做的事情:

    1. 您必须返回来自showLoader() 的承诺。
    2. showLoader() 完成时,您必须履行该承诺。
    3. 您必须将该承诺传递给 $.when()

    $.when() 通过向其传递一个或多个 Promise 来处理异步操作,然后它会监控这些 Promise 何时得到解决,并且仅当您传递给它的所有 Promise 都已解决时才解决它自己的 Promise。


    由于现在看来您要解决的真正问题是如何在其他代码运行之前强制重新绘制,您可以在此答案中看到如何做到这一点:When does the DOM repaint during Javascript routines?

    【讨论】:

    • 如果没有$.when,我也可以工作,但这里的问题是html rendering!!在渲染完成之前它不会显示加载器,因为我必须渲染大量的html,这使得用户认为由于页面变得无响应,所以点击没有发生!但是,如果我在showLoader() 函数调用之后保留alert 而不使用您的回答中提到的$.when,它将显示加载程序!这就是为什么我试图提出承诺!有什么解决办法吗??
    • @GuruprasadRao - 进行渲染显示是一个完全不同的问题。下一次,请在您的问题中说明实际的核心问题,而不是您在特定解决方案中遇到的问题,在这种情况下,恰好是完全错误的方向。我将添加一些信息,以便现在可以回答有关渲染问题的问题。仅供参考,不发布真正的问题是所谓的XY problem,这是一种非常确定的方式,可以让任何人都不可能给你最好的答案。
    • @GuruprasadRao - 我在我的答案中添加了一个链接,以了解如何解决重绘问题。
    • @jfried00.. 对不起!我会检查你提供的链接。但在这里我怀疑的是承诺本身,因为据我所知,$.when.then 应该根据我的尝试工作,是的,错过了一些部分,这可能是不工作的原因,你解释了它。所以我会接受这个作为答案!谢谢你的时间.. :)
    • @GuruprasadRao - 好的,很高兴你把它整理好了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-26
    • 1970-01-01
    • 1970-01-01
    • 2019-05-23
    • 1970-01-01
    • 2023-01-11
    • 1970-01-01
    相关资源
    最近更新 更多