我只发现了涉及类,事件处理程序和回调的相当复杂的答案(在我看来,这似乎是一种有点大锤的方法)。我认为回调可能有用但我似乎无法在最简单的上下文中应用这些。见这个例子:
<html>
<head>
<script type="text/javascript">
function myfunction() {
longfunctionfirst();
shortfunctionsecond();
}
function longfunctionfirst() {
setTimeout('alert("first function finished");',3000);
}
function shortfunctionsecond() {
setTimeout('alert("second function finished");',200);
}
</script>
</head>
<body>
<a href="#" onclick="javascript:myfunction();return false;">Call my function</a>
</body>
</html>
在此,第二个函数在第一个函数之前完成;什么是最简单的方法(或者有一个?)强制第二个函数延迟执行直到第一个函数完成?
--- ---编辑
所以这是一个垃圾的例子,但多亏了David Hedlund,我看到这个新的例子确实它是同步的(同时在测试过程中崩溃我的浏览器!):
<html>
<head>
<script type="text/javascript">
function myfunction() {
longfunctionfirst();
shortfunctionsecond();
}
function longfunctionfirst() {
var j = 10000;
for (var i=0; i<j; i++) {
document.body.innerHTML += i;
}
alert("first function finished");
}
function shortfunctionsecond() {
var j = 10;
for (var i=0; i<j; i++) {
document.body.innerHTML += i;
}
alert("second function finished");
}
</script>
</head>
<body>
<a href="#" onclick="javascript:myfunction();return false;">Call my function</a>
</body>
</html>
由于我的实际问题是jQuery和IE,如果我自己无法到达任何地方,我将不得不发布一个单独的问题!
答案 0 :(得分:44)
嗯,根据其定义,setTimeout
不会阻碍线程。这是可取的,因为如果它这样做,它会在等待的时间内冻结整个UI。如果你真的需要使用setTimeout
,那么你应该使用回调函数:
function myfunction() {
longfunctionfirst(shortfunctionsecond);
}
function longfunctionfirst(callback) {
setTimeout(function() {
alert('first function finished');
if(typeof callback == 'function')
callback();
}, 3000);
};
function shortfunctionsecond() {
setTimeout('alert("second function finished");', 200);
};
如果你不使用setTimeout
,但只是执行了很长时间的函数,并且正在使用setTimeout
来模拟它,那么你的函数 实际上是同步的,你根本不会遇到这个问题。但应该注意的是,AJAX请求是异步的,并且就像setTimeout
一样,在完成之前不会阻止UI线程。使用AJAX,与setTimeout
一样,您将不得不使用回调。
答案 1 :(得分:30)
在这段时间之后我回到了这个问题,因为我花了很长时间才找到我认为干净的解决方案: 强制执行我知道的javascript顺序执行的唯一方法是使用promises。 承诺详尽解释:Promises/A和Promises/A+
实现我知道的promises的唯一库是jquery所以这里是我如何使用jquery promises来解决这个问题:
<html>
<head>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script type="text/javascript">
function myfunction()
{
promise = longfunctionfirst().then(shortfunctionsecond);
}
function longfunctionfirst()
{
d = new $.Deferred();
setTimeout('alert("first function finished");d.resolve()',3000);
return d.promise()
}
function shortfunctionsecond()
{
d = new $.Deferred();
setTimeout('alert("second function finished");d.resolve()',200);
return d.promise()
}
</script>
</head>
<body>
<a href="#" onclick="javascript:myfunction();return false;">Call my function</a>
</body>
</html>
通过实现一个promise并使用.then()链接函数,确保第二个函数仅在第一个函数执行后执行 它是longfunctionfirst()中的命令d.resolve(),它给出了启动下一个函数的信号。
从技术上讲,shortfunctionsecond()不需要创建一个延迟并返回一个承诺,但我爱上了承诺并倾向于用承诺实现一切,抱歉。
答案 2 :(得分:11)
我是编程方面的老手,最近回到了我最近的热情,并努力适应这个面向对象,事件驱动的明亮的新世界,虽然我看到Javascript的非顺序行为的优势有时间它确实妨碍了简单性和可重用性。 我所做的一个简单例子就是拍照(用javascript,HTML,phonegap等编写的手机),调整大小并将其上传到网站上。 理想的顺序是:
所有这些都是一个非常简单的顺序程序,如果我们将每个步骤在完成时将控制权返回到下一个程序,但实际上:
顺便说一下,5个步骤中的4个涉及回调函数。
我的解决方案就是将每一步嵌套在前一步中并使用.onload和其他类似的策略,它看起来像这样:
takeAPhoto(takeaphotocallback(photo) {
photo.onload = function () {
resizePhoto(photo, resizePhotoCallback(photo) {
uploadPhoto(photo, uploadPhotoCallback(status) {
informUserOnOutcome();
});
});
};
loadPhoto(photo);
});
(我希望我没有犯太多错误,将代码带到它上面,真正的东西太过分散了注意力)
这是一个完美的例子,其中异步不好并且同步很好,因为与Ui事件处理相反,我们必须在执行下一步之前完成每一步,但代码是俄罗斯娃娃构造,这是令人困惑的并且难以实现,代码可重用性很难实现,因为所有的嵌套都很难将内部函数带入所需的所有参数,而无需依次将它们传递给每个容器或使用邪恶的全局变量,我本来希望所有这些代码的结果都会给我一个返回代码,但第一个容器将在返回代码可用之前完成。
现在回到Tom最初的问题,15年前使用C和哑电子板的简单程序是什么才是智能,易读,易于重用的解决方案?
这个要求实际上非常简单,我觉得我必须缺少对Javsascript和现代编程的基本理解,当然技术是为了提高生产力吗?
感谢您的耐心
恐龙雷蒙德; - )
答案 3 :(得分:1)
在javascript中,没有办法让代码等待。我遇到了这个问题,我这样做的方法是对服务器进行同步SJAX调用,服务器实际执行睡眠或在返回之前做一些活动,整个时间,js等待。
例如,同步AJAX:http://www.hunlock.com/blogs/Snippets:_Synchronous_AJAX
答案 4 :(得分:1)
在您的示例中,第一个函数在第二个函数启动之前实际完成。 setTimeout在达到超时之前不会执行该函数,它只会在后台启动一个计时器并在指定的时间后执行alert语句。
在JavaScript中没有本地的“睡眠”方式。你可以编写一个循环来检查时间,但这会给客户端带来很大的压力。你也可以像emacsian所描述的那样进行同步AJAX调用,但这会给你的服务器带来额外的负担。你最好的选择是避免这种情况,一旦你理解了setTimeout的工作方式,这对于大多数情况应该足够简单。
答案 5 :(得分:1)
我尝试了回调方式并且无法使其工作,您必须了解的是,即使执行不是,值仍然是原子的。例如:
alert('1');
&lt; ---这两个函数将同时执行
alert('2');
&lt; ---这两个函数将同时执行
但这样做会迫使我们知道执行的顺序:
loop=2;
total=0;
for(i=0;i<loop;i++) {
total+=1;
if(total == loop)
alert('2');
else
alert('1');
}
答案 6 :(得分:1)
如果您不坚持使用纯Javascript,则可以在Livescript中构建顺序代码,看起来相当不错。您可能需要查看this example:
# application
do
i = 3
console.log td!, "start"
<- :lo(op) ->
console.log td!, "hi #{i}"
i--
<- wait-for \something
if i is 0
return op! # break
lo(op)
<- sleep 1500ms
<- :lo(op) ->
console.log td!, "hello #{i}"
i++
if i is 3
return op! # break
<- sleep 1000ms
lo(op)
<- sleep 0
console.log td!, "heyy"
do
a = 8
<- :lo(op) ->
console.log td!, "this runs in parallel!", a
a--
go \something
if a is 0
return op! # break
<- sleep 500ms
lo(op)
输出:
0ms : start
2ms : hi 3
3ms : this runs in parallel! 8
3ms : hi 2
505ms : this runs in parallel! 7
505ms : hi 1
1007ms : this runs in parallel! 6
1508ms : this runs in parallel! 5
2009ms : this runs in parallel! 4
2509ms : hello 0
2509ms : this runs in parallel! 3
3010ms : this runs in parallel! 2
3509ms : hello 1
3510ms : this runs in parallel! 1
4511ms : hello 2
4511ms : heyy
答案 7 :(得分:1)
我有同样的问题,这是我的解决方案:
=INDEX($X$41:$X$47,MATCH(ROWS($Z$29:Z29),COUNTIF($Z$41:$Z$47,"<="&$Z$41:$Z$47),0))
=INDEX($Y$41:$Y$47,MATCH(ROWS($Z$29:Z29),COUNTIF($Z$41:$Z$47,"<="&$Z$41:$Z$47),0))
=INDEX($Z$41:$Z$47,MATCH(ROWS($Z$29:Z29),COUNTIF($Z$41:$Z$47,"<="&$Z$41:$Z$47),0))
答案 8 :(得分:0)
将代码放在字符串中,迭代,eval,setTimeout和递归以继续其余的行。毫无疑问,如果没有达到标准,我会对此进行改进或者将其抛弃。我的目的是用它来模拟真正的,非常基本的用户测试。
递归和setTimeout使它成为顺序。
思想?
var line_pos = 0;
var string =`
console.log('123');
console.log('line pos is '+ line_pos);
SLEEP
console.log('waited');
console.log('line pos is '+ line_pos);
SLEEP
SLEEP
console.log('Did i finish?');
`;
var lines = string.split("\n");
var r = function(line_pos){
for (i = p; i < lines.length; i++) {
if(lines[i] == 'SLEEP'){
setTimeout(function(){r(line_pos+1)},1500);
return;
}
eval (lines[line_pos]);
}
console.log('COMPLETED READING LINES');
return;
}
console.log('STARTED READING LINES');
r.call(this,line_pos);
输出
STARTED READING LINES
123
124
1 p is 0
undefined
waited
p is 5
125
Did i finish?
COMPLETED READING LINES