与jquery 1和2不同,jquery 3 ajax处理程序仅在完成处理程序代码后才执行新添加的html + js

时间:2017-08-25 10:01:57

标签: jquery jquery-deferred deferred jquery-3 jquery-2.0

我做了一个jsbin来表明问题: http://jsbin.com/dexeqiz/edit?html,js,output

有这个html:

<div id='log'></div>
<div id='scripts'></div>

和js:

$.get('...', function(){
    $('#scripts')
        .append("<script>$(function(){$('#log').append('<p>3</p>');});<\/script>");
    $('#log').append('<p>1</p>');
    $('#log').append('<p>2</p>');
});

在jquery 1和2中

它将在#log中呈现:
3
1
2

但在jquery 3中它将呈现
1
2
3

(所以只有在整个ajax处理程序完成后才添加3)

这是一个问题,因为有时我的代码需要在调用下一行之前执行之前附加的代码

现在我唯一的解决方法是将.append(newhtml)之后的代码放在setTimeout内,但我不愿意这样做,因为它看起来对用户来说稍微慢一些。我更愿意拥有像$.when(append).done(function(){code})

这样的东西

更新 似乎这种情况正在发生,因为从jQuery 3脚本开始,文档就绪$(function(){});加载异步(https://github.com/jquery/jquery/issues/1895)和 这是我目前的解决方案:http://jsbin.com/xayitec/edit?html,js,output

1 个答案:

答案 0 :(得分:1)

毕竟摆弄它很突出:这个问题没有真正的解决办法;至少没有一个不是非常hackish或没有改变整个设置/工作流程。

为了完整起见,我保留原样的“答案”(查看“LOG”下方的所有内容)并添加一些背景信息。


还有一个想法 - 非常hackish

您可以搜索要追加的字符串中的所有脚本。然后使用正则表达式搜索所有“$(function(){...})”事件,然后插入一个像“$(function(){...; executionHandler()})”这样的函数,它将倒计时直到所有这些结构已解决,然后设置一个外部承诺作为resovled。但是,正如我在开始时所说的那样,这将是相当严重的,也可能非常容易出错。


LOG

版本1,2,2.1和3都使用jQuery版本1.12.4,2.2.4和3.2.1进行了测试,并且应该适用于jQuery 1.8及更高版本的所有版本。

Version 1

$.get('...', function(){

    // make shure that $Deferred is in scope of all involved functions
    window.$Deferred = $.Deferred(); // get jQuery deferred object

    $('#scripts').append(
        "hi<script>$(function(){$('#log').append('<p>3</p>');});<\/script>" + // append your common stuff
        "<script>$(function(){$Deferred.resolve();})<\/script>" // add this line to resolve window.$Deferred
    );

    $Deferred.always(function() {
        // execute code after $Deferred was resolved or rejected
        $('#log').append('<p>1</p>');
        $('#log').append('<p>2</p>');
    });

});

Version 2

被踢了

Version 3

// $.get returns a jqXHR object which is a promise-compatible object
$.when($.get('...', function() {
    $('#scripts').append(
        "hi<script>$(function(){$('#log').append('<p>3</p>');});<\/script>"
    )
})).always(function( data, textStatus, jqXHR|errorThrown ) {
    // execute code when $.get is done or fails
    $('#log').append('<p>1</p>');
    $('#log').append('<p>2</p>');
});

或者

$.when($.get('...', function() {
    $('#scripts').append(
        "hi<script>$(function(){$('#log').append('<p>3</p>');});<\/script>"
    )
})).then(
    function( data, textStatus, jqXHR ) {
        // success callback
    },
    function( jqXHR, textStatus, errorThrown ) {
        // fail callback
    }
);

详细信息

参考