Javascript/jQuery:控制执行顺序(还没有ajax/php)

Javascript/jQuery:控制执行顺序(还没有ajax/php),javascript,jquery,settimeout,.when,Javascript,Jquery,Settimeout,.when,我花了好几个小时在网上阅读关于Javascript/jQuery中控制执行顺序的文章,但我仍然不明白 我试图编写代码,在网页上显示幕后javascript的执行进度。我有一个jsfiddle(),它使用超时来实现这一点。javascript是 var showProgress = function(x){ $(".progress").hide(); $(x).show(); } var step1 = function(){ showProgress(".run

我花了好几个小时在网上阅读关于Javascript/jQuery中控制执行顺序的文章,但我仍然不明白

我试图编写代码,在网页上显示幕后javascript的执行进度。我有一个jsfiddle(),它使用超时来实现这一点。javascript是

var showProgress = function(x){
    $(".progress").hide();
    $(x).show();   
}

var step1 = function(){
    showProgress(".running");
};

var step2 = function(){
    for(var i = 0; i < 1000000000; ++i) 
        i = i + 1; 
};

var step3 = function(){
    showProgress(".done");
};

$(".begin").click(function(){
    step1();
    setTimeout(step2, 0);
    setTimeout(step3, 0);
});

$(".clear").click(function(){
    $(".progress").hide();   
});
var showProgress = function(x){
    $(".progress").hide();
    $(x).show();   
}

var step1 = function(){
    var def = $.Deferred(); 
    showProgress(".running");
    return def.promise();
};

var step2 = function(){
    var def = $.Deferred(); 
    for(var i = 0; i < 1000000000; ++i) 
        i = i + 1; 
    return def.promise();
};

var step3 = function(){
    var def = $.Deferred(); 
    showProgress(".done");
    return def.promise();
};

var success = function(){
    console.log("success")   
};

var failure = function(){
    console.log("failure")   
};

$(".begin").click(function(){
    $.when(step1(), step2(), step3()).then(success, failure);
});

$(".clear").click(function(){
    $(".progress").hide();   
});
var showProgress=函数(x){
$(“.progress”).hide();
$(x).show();
}
var step1=函数(){
显示进度(“运行”);
};
var step2=函数(){
对于(变量i=0;i<100000000;+i)
i=i+1;
};
var step3=函数(){
显示进度(“完成”);
};
$(“.begin”)。单击(函数(){
步骤1();
设置超时(步骤2,0);
设置超时(步骤3,0);
});
$(“.clear”)。单击(函数(){
$(“.progress”).hide();
});
我最终需要使用ajax和php,我已经读到推荐的工具是when/then、延迟对象和承诺。所以我尝试了(),但是执行顺序是错误的。(当for循环运行时,html页面没有说“Running…”)

var showProgress = function(x){
    $(".progress").hide();
    $(x).show();   
}

var step1 = function(){
    showProgress(".running");
};

var step2 = function(){
    for(var i = 0; i < 1000000000; ++i) 
        i = i + 1; 
};

var step3 = function(){
    showProgress(".done");
};

$(".begin").click(function(){
    step1();
    setTimeout(step2, 0);
    setTimeout(step3, 0);
});

$(".clear").click(function(){
    $(".progress").hide();   
});
var showProgress = function(x){
    $(".progress").hide();
    $(x).show();   
}

var step1 = function(){
    var def = $.Deferred(); 
    showProgress(".running");
    return def.promise();
};

var step2 = function(){
    var def = $.Deferred(); 
    for(var i = 0; i < 1000000000; ++i) 
        i = i + 1; 
    return def.promise();
};

var step3 = function(){
    var def = $.Deferred(); 
    showProgress(".done");
    return def.promise();
};

var success = function(){
    console.log("success")   
};

var failure = function(){
    console.log("failure")   
};

$(".begin").click(function(){
    $.when(step1(), step2(), step3()).then(success, failure);
});

$(".clear").click(function(){
    $(".progress").hide();   
});
var showProgress=函数(x){
$(“.progress”).hide();
$(x).show();
}
var step1=函数(){
var def=$.Deferred();
显示进度(“运行”);
返回def.promise();
};
var step2=函数(){
var def=$.Deferred();
对于(变量i=0;i<100000000;+i)
i=i+1;
返回def.promise();
};
var step3=函数(){
var def=$.Deferred();
显示进度(“完成”);
返回def.promise();
};
var success=function(){
console.log(“成功”)
};
var failure=函数(){
console.log(“失败”)
};
$(“.begin”)。单击(函数(){
$.when(step1(),step2(),step3())。然后(success,failure);
});
$(“.clear”)。单击(函数(){
$(“.progress”).hide();
});
问题1(第一小提琴):当我将“$(“.begin”)中的“step1()”更改为“setTimeout(step1,0)”。单击(function(){..}”块时,执行顺序会中断。这是为什么

问题2(第二个问题):为什么当我尝试使用when/then/Deferred/promise时,执行顺序是错误的

问题3(第二部分):为什么“success”函数没有执行?我告诉它打印到控制台,但Chrome的Javascript控制台没有显示任何内容

为什么当我尝试使用when/then/Deferred/promise(第二副手)时,时机不对

因为您没有使用任何
setTimeout
s,因此可以有效地同步执行所有操作。在完成处理之前,浏览器不会重新渲染屏幕,并且您只会看到最后出现的
Done

使用承诺/延迟不会使代码异步!您必须自己处理这一点:

function step…(){
    var def = $.Deferred(); 
    setTimeout(function() {
        …
    }, 0);
    return def.promise();
};
此外,立即调用
step1()、step2()、step3()
(然后将承诺传递给
$。当
等待所有问题解决时)将并行运行异步函数,这不是您想要的。要链接它们,请使用

step1().then(step2).then(step3).then(success, failure);
为什么“success”函数不执行(次要)

因为您的承诺永远不会得到解决。当您完成异步任务时,您需要告诉延迟者(通常传递结果值)。您在代码中的承诺永远挂起,永远不会执行任何处理程序

固定的:

function step1() {
    var def = $.Deferred();
    setTimeout(function() {
        showProgress(".running");
        def.resolve();
    }, 0);
    return def.promise();
}

function step2() {
    var def = $.Deferred();
    setTimeout(function() {
       for(var i = 0; i < 1000000000; ++i) 
            i = i + 1;
        def.resolve();
    }, 0);
    return def.promise();
}

function step3() {
    var def = $.Deferred();
    setTimeout(function() {
       showProgress(".done");
        def.resolve();
    }, 0);
    return def.promise();
}
函数步骤1(){
var def=$.Deferred();
setTimeout(函数(){
显示进度(“运行”);
def.resolve();
}, 0);
返回def.promise();
}
函数step2(){
var def=$.Deferred();
setTimeout(函数(){
对于(变量i=0;i<100000000;+i)
i=i+1;
def.resolve();
}, 0);
返回def.promise();
}
函数step3(){
var def=$.Deferred();
setTimeout(函数(){
显示进度(“完成”);
def.resolve();
}, 0);
返回def.promise();
}

由于函数本身不是异步的,您也可以选择立即执行操作,只放置
setTimeout(def.resolve,0)
并仅延迟处理程序;您也可以同时执行这两种操作。

Question 1:这是指代码段1还是2(有延迟还是没有延迟)?您能否更具体地说明“分解”问题,你观察到了什么?问题2:“错误”到底是什么?发生了什么意外的顺序?问题1指的是片段1,没有延迟。正确的执行顺序是:用户按下“开始”按钮,出现一个写着“正在运行…”的框,出现一个大的长for循环,然后出现一个写着“正在运行…”的框替换为一个写着“完成”的框。在我在问题1和问题2中描述的情况下,“Running…”框显示的时间不够长,无法实际看到。我认为它出现在for循环之后,并立即替换为“Done”我认为JSFIDLE比这个解释更清楚。所以顺序总是正确的,但不是时间。“不幸的是”,第一个FIDLE对我来说很好,即使在
setTimeout
中切换,你用什么浏览器来体验这个呢?我用的是Chrome(v36.0.1985.143).执行顺序和计时有什么区别?顺序意味着按照正确的顺序执行步骤(1-2-3而不是2-3-1),而计时指的是步骤之间的(时间)间隔(1-2-3而不是12---3)。我要补充的是,OP应该记住在延迟失败时调用拒绝,否则将永远不会调用失败的回调。关于问题1,我没有证据表明它为什么不能与第三个
setTimeout
一起工作,但猜测是a)0超时太低(实际上至少有4ms)b)具有相同延迟的超时被安排在一起-因此在某些浏览器中,优化可能会跳入,而不是在这两者之间进行渲染,就像在同步情况下一样。@MikeCheel:当然,“解决”意味着满足和拒绝,无论什么都是合适的。在这种情况下,它们几乎不会失败:-)Si