如何在多个变更事件上使用jQuery Promise [英] How to use jQuery promise on multiple change events
问题描述
我有以下代码,该代码使用基本的选项链父/子关系显示和隐藏选择菜单.进行更改后,我需要调用一个函数.
I've got the following code which shows and hides select menus using a basic options chain parent/child relationship. Once there is a change I need to call a function.
目前,我正在按照以下说明进行操作,每个<select>
的更改都会触发一个事件,然后调用该函数.在现实生活中,这是一个ajax调用,但这与问题无关.
Currently I am doing it as demonstrated below, triggering an event on change for each <select>
, which then calls the function. In real life this is an ajax call but that is irrelevant to the question.
我下面的代码有效.我要解决的问题是我如何不依赖更改事件就能完成此操作,因为它不必要地多次触发该函数.我只想在更改父对象时将函数调用放在$.each()
循环的末尾,但是由于涉及到动画,由于有问题的元素有时仍然可见/隐藏,因此它将失败.我通过在每个slideUp()
和slideDown()
内放置一个回调来解决此问题,但这正是我最终多次触发事件的确切原因.
The code I have below works. The problem I would like to solve is how I can accomplish this without relying on a change event since it triggers the function multiple times unnecessarily. I'd like to simply place a function call at the end of the $.each()
loop when the parent is changed but because of the animation involved it will fail since the elements in question are sometimes still visible/hidden. I solved this by placing a callback inside each slideUp()
and slideDown()
but this is the exact reason I end up triggering things multiple times.
我强烈希望找到的答案使用jQuery promise()
,其中指出:
I have a strong feeling that the answer I am looking for uses jQuery promise()
which states:
.promise()方法返回一个动态生成的Promise,一旦绑定到该集合的某种类型的所有操作(无论是否排队)都已解决,则该Promise将得到解决.
The .promise() method returns a dynamically generated Promise that is resolved once all actions of a certain type bound to the collection, queued or not, have ended.
这正是我想要做的,但是我对promise()
完全困惑,这是正确的用法.我理解了这个概念,但是我可以使用一些帮助来理解如何将所有更改事件排队到一个promise()
中,然后在它们全部完成后调用我的函数.
That is exactly what I want to do but I am utterly confused by promise()
and it's proper usage. I get the concept, but I could use some help understanding how I can queue all those change events into one promise()
and then call my function when they are all complete.
$('select[data-parent="true"]').change(function() {
var parentValue = +this.value;
var parentId = $(this).data('parent_id');
$('div[data-parent_id="' + parentId + '"]').each(function() {
var parentValues = $(this).data('parent_values');
if (parentValues.indexOf(parentValue) !== -1) {
$(this).slideDown(1000, function() {
$(this).find('select').change();
});
} else {
$(this).slideUp(1000, function() {
$(this).find('select').change();
});
}
});
});
$('select').on('change', function() {
var results = '';
$('div.option').each(function() {
results += $(this).find('select').prop('name') + ' IS VISIBLE: ' + +$(this).is(':visible') + '<br>';
});
$('#results').html(results);
});
div {
padding: 5px 10px;
}
div.child {
display: none
}
select {
width: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<div class="option">
<select name="container" data-parent="true" data-parent_id="10">
<option value="">--- Select a container---</option>
<option value="1">Box</option>
<option value="2">Bag</option>
<option value="3">Pallet</option>
</select>
</div>
<div class="child option" data-parent_id="10" data-parent_values="[1]">
<select name="box color">
<option value="100">Red</option>
<option value="200">Blue</option>
</select>
</div>
<div class="child option" data-parent_id="10" data-parent_values="[2]">
<select name="bag color">
<option value="300">Green</option>
<option value="400">Yellow</option>
</select>
</div>
<div class="child option" data-parent_id="10" data-parent_values="[3]">
<select name="pallet color">
<option value="500">Black</option>
<option value="600">Yellow</option>
</select>
</div>
<div id="results">
</div>
推荐答案
由于jQuery动画可以返回诺言.promise()
并使用.map
而不是.each
-代码可以很简单:
As jQuery animations can return promises .promise()
and using .map
instead of .each
- the code can be simply:
$('select[data-parent="true"]').change(function() {
var parentValue = +this.value;
var parentId = $(this).data('parent_id');
$.when.apply($, $('div[data-parent_id="' + parentId + '"]').map(function(i, v) {
var parentValues = $(this).data('parent_values');
if (parentValues.indexOf(parentValue) !== -1) {
return $(this).slideDown(1000).promise();
} else {
return $(this).slideUp(1000).promise();
}
})).done(function() {
var results = '';
$('div.option').each(function() {
results += $(this).find('select').prop('name') + ' IS VISIBLE: ' + +$(this).is(':visible') + '<br>';
});
$('#results').html(results);
});
});
div {
padding: 5px 10px;
}
div.child {
display: none
}
select {
width: 200px;
margin: 4px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<div class="option">
<select name="container" data-parent="true" data-parent_id="10">
<option value="">--- Select a container---</option>
<option value="1">Box</option>
<option value="2">Bag</option>
<option value="3">Pallet</option>
</select>
</div>
<div class="child option" data-parent_id="10" data-parent_values="[1]">
<select name="box color">
<option value="100">Red</option>
<option value="200">Blue</option>
</select>
</div>
<div class="child option" data-parent_id="10" data-parent_values="[2]">
<select name="bag color">
<option value="300">Green</option>
<option value="400">Yellow</option>
</select>
</div>
<div class="child option" data-parent_id="10" data-parent_values="[3]">
<select name="pallet color">
<option value="500">Black</option>
<option value="600">Yellow</option>
</select>
</div>
<div id="results">
</div>
这篇关于如何在多个变更事件上使用jQuery Promise的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!