在 jQuery 循环中正确使用 async/await 的方法是:

huangapple go评论54阅读模式
英文:

Correct way to use async/await inside Jquery loop

问题

我在我的脚本中有以下的JQuery代码。在这个代码中,我试图在saveQuestion函数内发生一系列的ajax调用时显示加载图标。

但是加载功能没有发生,而是按顺序调用了ajax调用。

我正在尝试以下代码。请提供任何想法。

$(document).on("click", ".update_qualify_question", function (e) {	

	var btnObj  = $(".update_qualify_question");
	var btnTxt = btnObj.text();
	btnObj.html('Processing <i class="fa fa-spinner fa-spin"></i>');
	btnObj.attr('disabled', 'disabled');
	
	(async function() {
		$(this).closest('.conditional_qa_portion').find(".current_question").each(async function(){
			await saveQuestion($(this), 1);
		})
	
	})();
       
		btnObj.html(btnTxt); 
		btnObj.removeAttr('disabled');	
				
});
英文:

I am having the below JQuery code in my script. In this I am trying to show the loading icon when series of ajax calls happens inside saveQuestion function.

But the loading functionality is not happened but the calling ajax call is happened in sequence.

I am trying the below code. Please suggest any idea

$(document).on(&quot;click&quot;, &quot;.update_qualify_question&quot;, function (e) {	

	var btnObj  = $(&quot;.update_qualify_question&quot;);
	var btnTxt = btnObj.text();
	btnObj.html(&#39;Processing &lt;i class=&quot;fa fa-spinner fa-spin&quot;&gt;&lt;/i&gt;&#39;);
	btnObj.attr(&#39;disabled&#39;, &#39;disabled&#39;);
	
	(async function() {
		$(this).closest(&#39;.conditional_qa_portion&#39;).find(&quot;.current_question&quot;).each(async function(){
			await saveQuestion($(this), 1);
		})
	
	})();
       
		btnObj.html(btnTxt); 
		btnObj.removeAttr(&#39;disabled&#39;);	
				
});

答案1

得分: 1

以下是翻译好的部分:

这里发生的情况是,您的函数没有等待异步代码的结果,这意味着您更改按钮文本,然后立即将其更改回来,这导致文本似乎没有更改。

btnObj.html('Processing <i class="fa fa-spinner fa-spin"></i>');
// not awaited so don't stop execution
(async function() {
  $(this)
    .closest('.conditional_qa_portion')
    .find(".current_question")
    .each(async function() {await saveQuestion($(this), 1);});
})();
// ran immediately
btnObj.html(btnText);

有两个问题需要等待代码,您在 .each 中有一个异步调用,没有办法等待它,还有您创建并立即调用的匿名函数。

您可以像这样使用 async/await:

$(document).on("click", ".update_qualify_question", async function (e) {  
    const btnObj  = $(e.currentTarget);
    const btnTxt = btnObj.text();
    btnObj.html('Processing <i class="fa fa-spinner fa-spin"></i>');
    btnObj.attr('disabled', 'disabled');
    // not sure what element you wanted to do closest on since you had nested function so this wasn't the button (which is what I believe you meant)
    const elms = btnObj      
        .closest('.conditional_qa_portion')
        .find(".current_question")
        .toArray();
    for(const elm of elms) {
    	await saveQuestion($(elm), 1);
    }
    btnObj.html(btnTxt); 
    btnObj.removeAttr('disabled');              
});

使用这种方式,我们可以等待每个数据调用完成,然后再允许点击按钮。我们使用 .toArray() 来获取列表,以便我们可以在 for 循环中等待结果,因为 .each() 没有办法等待结果。

英文:

What is happening here is that your function isn't awaiting on the results of the asynchronous code, this means you are changing the button text then immediately changing it back, which leads to the appearance that the text hasn't changed.

btnObj.html(&#39;Processing &lt;i class=&quot;fa fa-spinner fa-spin&quot;&gt;&lt;/i&gt;&#39;);
// not awaited so don&#39;t stop execution
(async function() {
  $(this)
    .closest(&#39;.conditional_qa_portion&#39;)
    .find(&quot;.current_question&quot;)
    .each(async function() {await saveQuestion($(this), 1);});
})();
// ran immediately
btnObj.html(btnText);

there are two issues with awaiting on the code, you have the async call in the .each which has no way to be awaited for and the anonymous function you created and called immediately.

you could do something like this using async/await:

$(document).on(&quot;click&quot;, &quot;.update_qualify_question&quot;, async function (e) {  
    const btnObj  = $(e.currentTarget);
    const btnTxt = btnObj.text();
    btnObj.html(&#39;Processing &lt;i class=&quot;fa fa-spinner fa-spin&quot;&gt;&lt;/i&gt;&#39;);
    btnObj.attr(&#39;disabled&#39;, &#39;disabled&#39;);
    // not sure what element you wanted to do closest on since you had nested function so this wasn&#39;t the button (which is what I believe you meant)
    const elms = btnObj      
        .closest(&#39;.conditional_qa_portion&#39;)
        .find(&quot;.current_question&quot;)
        .toArray();
    for(const elm of elms) {
    	await saveQuestion($(elm), 1);
    }
    btnObj.html(btnTxt); 
    btnObj.removeAttr(&#39;disabled&#39;);              
});

With this we can wait till each data call is done before allowing the button to be clicked again. we use .toArray() to get the list so that we can await on the results in a for of loop since the .each() has no way for us to await on the results.

huangapple
  • 本文由 发表于 2023年7月12日 22:47:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/76671840.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定