여기에 무슨 일이 일어나고 있는지에 대한 고안된 예가 있습니다 : http://jsfiddle.net/adamjford/YNGcm/20/
HTML :
<a href="#">Click me!</a>
<div></div>
자바 스크립트 :
function getSomeDeferredStuff() {
var deferreds = [];
var i = 1;
for (i = 1; i <= 10; i++) {
var count = i;
deferreds.push(
$.post('/echo/html/', {
html: "<p>Task #" + count + " complete.",
delay: count
}).success(function(data) {
$("div").append(data);
}));
}
return deferreds;
}
$(function() {
$("a").click(function() {
var deferreds = getSomeDeferredStuff();
$.when(deferreds).done(function() {
$("div").append("<p>All done!</p>");
});
});
});
나는 “모두 끝났어!” 모든 지연된 작업이 완료된 후에 표시되지만 $.when()
지연된 개체 배열을 처리하는 방법을 알지 못하는 것 같습니다. “다됐다!” 배열이 Deferred 객체가 아니기 때문에 먼저 발생하므로 jQuery가 진행되어 방금 완료된 것으로 가정합니다.
나는 객체를 함수에 전달할 수 있다는 것을 알고 $.when(deferred1, deferred2, ..., deferredX)
있지만 해결하려는 실제 문제에서 얼마나 많은 지연 객체가 실행 될지 알 수 없습니다.
답변
에 값의 배열을 전달하려면 어떤 일반적으로 그들에게 별도의 매개 변수를 사용하는 것으로 기대하는 기능 Function.prototype.apply
이 경우에 당신이 필요합니다 :
$.when.apply($, my_array).then( ___ );
http://jsfiddle.net/YNGcm/21/ 참조
ES6에서는 ...
스프레드 연산자를 대신 사용할 수 있습니다 .
$.when(...my_array).then( ___ );
두 경우 모두 .then
처리기에 필요한 공식 매개 변수의 수를 미리 알지 못할 가능성이 높으므로 arguments
해당 약속의 결과를 검색하려면 해당 처리기가 배열 을 처리해야합니다 .
답변
(감사합니다!) 위의 해결 방법은 제대로의 연기에 제공되는 객체 돌아 가지의 문제를 해결하지 않는 resolve()
jQuery를가 호출 때문에 방법 done()
과 fail()
각각의 매개 변수가 아닌 배열과 콜백을. 즉, arguments
의사 배열 을 사용하여 지연된 배열에서 반환 된 모든 확인 / 거부 된 개체를 가져와야합니다.
$.when.apply($,deferreds).then(function() {
var objects=arguments; // The array of resolved objects as a pseudo-array
...
};
지연된 배열을 전달 했으므로 결과 배열을 다시 가져 오는 것이 좋습니다. 의사 배열 대신 실제 배열을 다시 가져 와서 같은 메소드를 사용할 수도 있습니다 Array.sort()
.
다음은 이러한 문제를 해결 하는 when.js 의 when.all()
방법에서 영감을 얻은 솔루션입니다 .
// Put somewhere in your scripting environment
if (typeof jQuery.when.all === 'undefined') {
jQuery.when.all = function (deferreds) {
return $.Deferred(function (def) {
$.when.apply(jQuery, deferreds).then(
function () {
def.resolveWith(this, [Array.prototype.slice.call(arguments)]);
},
function () {
def.rejectWith(this, [Array.prototype.slice.call(arguments)]);
});
});
}
}
이제 지연 / 프로 미스 배열을 전달하고 콜백에서 해결 / 거부 된 오브젝트 배열을 다음과 같이 다시 가져올 수 있습니다.
$.when.all(deferreds).then(function(objects) {
console.log("Resolved objects:", objects);
});
답변
when
메소드를 배열에 적용 할 수 있습니다 .
var arr = [ /* Deferred objects */ ];
$.when.apply($, arr);
답변
여러 개의 병렬 AJAX 호출을 호출 할 때 각 응답을 처리하기위한 두 가지 옵션이 있습니다.
- 동기식 AJAX 호출을 사용하십시오.
Promises'
array를 사용 하고 s$.when
를 수락promise
하고.done
모든promise
응답이 각 응답으로 성공적으로 반환 되면 콜백 이 호출됩니다 .
예
function ajaxRequest(capitalCity) {
return $.ajax({
url: 'https://restcountries.eu/rest/v1/capital/'+capitalCity,
success: function(response) {
},
error: function(response) {
console.log("Error")
}
});
}
$(function(){
var capitalCities = ['Delhi', 'Beijing', 'Washington', 'Tokyo', 'London'];
$('#capitals').text(capitalCities);
function getCountryCapitals(){ //do multiple parallel ajax requests
var promises = [];
for(var i=0,l=capitalCities.length; i<l; i++){
var promise = ajaxRequest(capitalCities[i]);
promises.push(promise);
}
$.when.apply($, promises)
.done(fillCountryCapitals);
}
function fillCountryCapitals(){
var countries = [];
var responses = arguments;
for(i in responses){
console.dir(responses[i]);
countries.push(responses[i][0][0].nativeName)
}
$('#countries').text(countries);
}
getCountryCapitals()
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<h4>Capital Cities : </h4> <span id="capitals"></span>
<h4>Respective Country's Native Names : </h4> <span id="countries"></span>
</div>
답변
필요없는 간단한 대안으로 $.when.apply
또는 array
여러 병렬 약속에 대한 하나의 약속을 생성하기 위해 다음과 같은 패턴을 사용할 수 있습니다 :
promise = $.when(promise, anotherPromise);
예 :
function GetSomeDeferredStuff() {
// Start with an empty resolved promise (or undefined does the same!)
var promise;
var i = 1;
for (i = 1; i <= 5; i++) {
var count = i;
promise = $.when(promise,
$.ajax({
type: "POST",
url: '/echo/html/',
data: {
html: "<p>Task #" + count + " complete.",
delay: count / 2
},
success: function (data) {
$("div").append(data);
}
}));
}
return promise;
}
$(function () {
$("a").click(function () {
var promise = GetSomeDeferredStuff();
promise.then(function () {
$("div").append("<p>All done!</p>");
});
});
});
노트:
- 나는 누군가 체인을 사용하여 순차적으로 약속을보고 나서 이것을 알아 냈습니다.
promise = promise.then(newpromise)
- 단점은 씬 뒤에 여분의 약속 객체를 만들고 끝에 전달 된 매개 변수는 유용하지 않습니다 (추가 객체 안에 중첩되어 있기 때문에). 짧고 간단하지만 원하는 것을 위해.
- 단점은 어레이 또는 어레이 관리가 필요하지 않다는 것입니다.
답변
$ .each를 사용하여 다른 것을 제안하고 싶습니다.
-
우리는 다음과 같이 아약스 함수를 선언 할 수있다 :
function ajaxFn(someData) { this.someData = someData; var that = this; return function () { var promise = $.Deferred(); $.ajax({ method: "POST", url: "url", data: that.someData, success: function(data) { promise.resolve(data); }, error: function(data) { promise.reject(data); } }) return promise; } }
-
우리가 보낼 아약스로 함수 배열을 생성하는 코드의 일부 :
var arrayOfFn = []; for (var i = 0; i < someDataArray.length; i++) { var ajaxFnForArray = new ajaxFn(someDataArray[i]); arrayOfFn.push(ajaxFnForArray); }
-
그리고 아약스를 전송하여 함수를 호출 :
$.when( $.each(arrayOfFn, function(index, value) { value.call() }) ).then(function() { alert("Cheer!"); } )
답변
코드를 변환하고 ES6에 액세스 할 수있는 경우 객체의 반복 가능한 각 항목을 개별 인수로 구체적으로 적용하는 스프레드 구문을 $.when()
필요에 따라 사용할 수 있습니다.
$.when(...deferreds).done(() => {
// do stuff
});