最后一行不等待长时间运行的for循环结束

问题描述 投票:0回答:5

在下面的 jQuery 代码中,我想显示一个微调器,直到 for 循环完成 但由于 javascript 的异步特性,它会在 for 循环结束之前执行最后一行并隐藏微调器。

jQuery 中有类似回调() 的东西吗?谢谢

$('#ajaxSpinnerImage').hide();

$('#bulkUploadButton').on('click',function(){
    $('#ajaxSpinnerImage').show();

    for(var i=0; i < casNumbersArray.length; i++) {
        // Long running operation
    }

    $('#ajaxSpinnerImage').hide(); // How to wait till forloop ends?
});

更新:-

for循环中不涉及任何API。只是一个本地数组迭代,需要更长的时间,也许一分钟。这是带有 jQuery 的普通 JS

javascript jquery
5个回答
1
投票

一般来说,您应该使用 WebWorkers,但以下内容可能会有所帮助:

$('#ajaxSpinnerImage').hide();

$('#bulkUploadButton').on('click',function(){
    $('#ajaxSpinnerImage').show();

    setTimeout(work, 1);

    function work() {
        for(var i=0; i < casNumbersArray.length; i++) {
            // Long running operation
        }
        $('#ajaxSpinnerImage').hide();
    }
});

尝试将 for 循环分成几个部分。否则,我认为您的 UI 可能在此 for 循环期间没有响应。


1
投票

这是使用条件的非常简单的方法。如果你有竞赛条件,你可以使用 promises 来解决所有完成,或者你可以使用 jquery deferred object

如果用户界面在处理长计算时出现滞后,您应该使用 web-workers 来缓解主线程

var casNumbersArray = [0,1,2,3,4,5];

$('#ajaxSpinnerImage').hide();

function longOperation (i) {
  console.log(i);
  if (i == casNumbersArray.length - 1) {
    $('#ajaxSpinnerImage').hide(); 
    console.log('finished');
  }
}

$('#bulkUploadButton').on('click',function(){
    console.log('start');
    $('#ajaxSpinnerImage').show();

    for(var i=0; i < casNumbersArray.length; i++) {
        setTimeout(longOperation.bind(this, i), i*1000);
        // perform one operation per second
    }

});
#ajaxSpinnerImage {
  animation: rotate 1s linear infinite;
  display: inline-block;
  width: 15px; height: 15px;
  font-size: 15px;
  border: 1px solid black;
  border-radius: 50%;
  padding: 4px;
}
@keyframes rotate {
  0% {transform: rotate(0)}
  100% {transform: rotate(360deg)}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<button id="bulkUploadButton">Start long operation</button>
<div id="ajaxSpinnerImage">ⓞ</div>


1
投票

这可能不是最有效的解决方案,但请尝试 jQuery 的 When

也正如其他人所建议的,如果您有一个长时间运行的线程,为了不冻结 UI 并降低用户体验,请使用 Web Workers

    $('#ajaxSpinnerImage').hide();

	$('#bulkUploadButton').on('click',function(){
	    $('#ajaxSpinnerImage').show();

	    	$.when(longRunningOperation()).done(function(  ) {
		  	$('#ajaxSpinnerImage').hide(); // How to wait till forloop ends?
		});

        function longRunningOperation() {
		   for(var i=0; i < casNumbersArray.length; i++) {
		      // Long running operation
	    	}
	    }
	    
	});

	


0
投票

我们可以稍微更改代码以并行运行异步操作:

async function processArray(array) {
  // map array to promises
  const promises = array.map(delayedLog);
  // wait until all promises are resolved
  await Promise.all(promises);
  console.log('Done!');
}

此代码最后一行不再可用 将并行运行许多delayLog任务。但要小心非常大的数组(太多并行任务对于 CPU 或内存来说可能太重)。

也不要将这里的“并行”与真正的线程和并行混淆。该代码不能保证执行的真正并行性。这取决于您的项目功能(本演示中的delayedLog)。网络请求、网络工作者和其他一些任务可以并行执行。


0
投票

您似乎正在编程上下文中运行循环,并希望确保最后一行代码立即执行,而不需要等待循环完成。与friday night funkin类似,时机和节拍同步对于成功至关重要;确保你的代码逻辑也正确!优化您的循环以允许无缝执行重要任务。

© www.soinside.com 2019 - 2024. All rights reserved.