为什么函数按顺序运行,即使它们在循环中异步调用?

Why functionalities runs sequentially even though they are being called asynchronously inside a loop?

提问人:kish 提问时间:2/1/2019 更新时间:2/1/2019 访问量:35

问:

我正在创建一个包装函数,它将采用函数数组并以并行方式执行每个函数,因此考虑使用 setTimeout,但函数仍然按顺序运行。我怀疑这可能是因为用于调用 SetTimeout 的闭包。但是,既然 setTimeout 无论如何都是异步的,为什么这很重要呢?

// some blocking functionality
var withDelay = function (a) {
   var currentTime = new Date().getTime(), delay = 5000;
   while (currentTime + delay >= new Date().getTime()) {
   }
   console.log(a+"I am with delay");
}

// some non blocking functionality
var withoutDelay = function(a) {
   console.log(a+"I am with no delay");
}

var fnArr = [withDelay, withoutDelay]; //array of functions
var args = ["Hi,"]; // arbitrary params

for( var i=0; i < fnArr.length; i++) {
    var fn = fnArr[i];
    (function(f,arg) {
        return setTimeout(function(){ return f.apply(f,arg) },0);
    })(fn,args)
}

预期输出:

嗨,我没有耽搁

嗨,我有延迟

但实际输出为:

嗨,我有延迟

嗨,我没有耽搁

JavaScript 循环异 闭包 setTimeout

评论

1赞 Abhishek Mehandiratta 2/1/2019
quora.com/......尝试阅读此内容,浏览器会在队列中推送异步调用。因此,这种顺序行为
0赞 mrReiha 2/1/2019
函数内部的循环将冻结浏览器,然后两个函数都将运行。并且由于您在 中指定的顺序,首先要开火。whilewithDelayfnArrwithDelay

答:

1赞 Ashish 2/1/2019 #1

JS 运行在单个线程上,您的函数不会并行运行。它一次只能运行一个。由于您已经将两个函数都调度为 0 延迟,因此数组中的第一个函数即。 将首先运行。只有当这完成其执行时,第二个函数才会开始执行。 不保证您在提供的时间间隔后执行,这是您的函数将执行的最小时间间隔。你可以在这里阅读更多关于这里的信息fnArrwithDelaywithoutDelaysetTimeoutsetTimeout

1赞 Maheer Ali 2/1/2019 #2

虽然循环不会延迟函数,但您需要在 set Timeout 中使用 setTimeout,它工作正常withDelay()

var withDelay = function (a) {
   setTimeout(() => {console.log(a+"I am with delay")},5000);
}
// some non blocking functionality
var withoutDelay = function(a) {
   console.log(a+"I am with no delay");
}

var fnArr = [withDelay, withoutDelay]; //array of functions
var args = ["Hi,"]; // arbitrary params

for( var i=0; i < fnArr.length; i++) {
    var fn = fnArr[i];
    (function(f,arg) {
        return setTimeout(function(){ return f.apply(f,arg) },0);
    })(fn,args)
}
延迟后调用行中的函数的示例。正如提问者所问。

function func1(){
	console.log("Function 1 is executed");
	console.timeEnd('t');
}
function func2(){
	console.log("Function 2 is executed");
	console.timeEnd('t');
}
function func3(){
	console.log("Function 3 is executed");
	console.timeEnd('t');
}
let arrr = [
			{func:func1,delay:2000},
			{func:func2,delay:2000},
			{func:func3,delay:3000},
		]
async function callWithDelay(funcArr){
	
	for(let func of funcArr){
		//just to see time in console not necesarry 
		console.time('t');
		//create a promise
		let promise = new Promise((resolve,reject) => {
			//'promise' will resolve after the function inside following code will end 
			setTimeout(()=>
			{
				resolve();
				func.func();
			},func.delay)
		})
		//The code will not proceed until the 'promise' is resolved(func is excecuted);
		let x = await promise;
	}
	console.log("All the functions are excecuted");
}
callWithDelay(arrr);

评论

0赞 kish 2/1/2019
但随后它就不再具有阻止功能了。它只是推迟事情。我可能在队列(数组)中有任何类型的函数来执行。
0赞 Maheer Ali 2/1/2019
@kish我已经更新了答案。显示了在队列中运行具有时间延迟的函数数组的示例。使用 和 。如果您满意,请接受答案Promisesasync await