지연된 배열을 $ .when ()에 전달
여기에 무슨 일이 일어나고 있는지 생각해 본 예가 있습니다 : 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을 사용 하고을$.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
});
angularJS 또는 Q promise 라이브러리의 변형을 사용하는 .all()
경우이 정확한 문제를 해결 하는 방법이 있습니다.
var savePromises = [];
angular.forEach(models, function(model){
savePromises.push(
model.saveToServer()
)
});
$q.all(savePromises).then(
function success(results){...},
function failed(results){...}
);
전체 API를 참조하십시오 :
https://github.com/kriskowal/q/wiki/API-Reference#promiseall
https://docs.angularjs.org/api/ng/service/$q
각 루프에 게시 한 다음 아약스에서받은 숫자의 일부 필드에서 html 마크 업을 설정하는 경우와 매우 비슷한 경우가있었습니다. 그런 다음이 필드의 (현재 업데이트 된) 값의 합계를 수행하고 총 필드에 배치해야했습니다.
따라서 문제는 모든 숫자에 대한 합계를 시도했지만 비동기 ajax 호출에서 아직 데이터가 도착하지 않았다는 것입니다. 코드를 재사용하려면 몇 가지 기능으로이 기능을 완료해야했습니다. 내 외부 함수는 데이터를 기다린 다음 완전히 업데이트 된 DOM으로 작업을 수행합니다.
// 1st
function Outer() {
var deferreds = GetAllData();
$.when.apply($, deferreds).done(function () {
// now you can do whatever you want with the updated page
});
}
// 2nd
function GetAllData() {
var deferreds = [];
$('.calculatedField').each(function (data) {
deferreds.push(GetIndividualData($(this)));
});
return deferreds;
}
// 3rd
function GetIndividualData(item) {
var def = new $.Deferred();
$.post('@Url.Action("GetData")', function (data) {
item.html(data.valueFromAjax);
def.resolve(data);
});
return def;
}
참고 URL : https://stackoverflow.com/questions/5627284/pass-in-an-array-of-deferreds-to-when
도와주세요.
'development' 카테고리의 다른 글
명령 행에서 R 스크립트 실행 (0) | 2020.02.18 |
---|---|
UnicodeDecodeError : 'charmap'코덱은 Y 위치에서 바이트 X를 디코딩 할 수 없습니다. (0) | 2020.02.18 |
git mark를 삭제하고 새 파일을 파일 이동으로 만드는 방법은 무엇입니까? (0) | 2020.02.17 |
다른 포크에서 병합되지 않은 업스트림 풀 요청을 포크에 적용하는 방법은 무엇입니까? (0) | 2020.02.17 |
RSpec let ()을 언제 사용합니까? (0) | 2020.02.17 |