jQuery를 사용한 병렬 비동기 Ajax 요청
여러 ajax/json 요청 결과에 따라 페이지를 업데이트하고 싶습니다.jQuery를 사용하면 다음과 같이 콜백을 "체인"할 수 있습니다.
$.getJSON("/values/1", function(data) {
// data = {value: 1}
var value_1 = data.value;
$.getJSON("/values/2", function(data) {
// data = {value: 42}
var value_2 = data.value;
var sum = value_1 + value_2;
$('#mynode').html(sum);
});
});
단, 이로 인해 요구가 연속적으로 이루어집니다.요청을 병행하여 페이지 갱신을 하는 것이 좋습니다.어떻게 할 수 있을까요?
jQuery $.when() 및 $.done()이 바로 필요한 항목입니다.
$.when($.ajax("/page1.php"), $.ajax("/page2.php"))
.then(myFunc, myFailure);
특정 수의 병렬 쿼리를 지원할 수 있는 이 솔루션을 사용해 보십시오.
var done = 4; // number of total requests
var sum = 0;
/* Normal loops don't create a new scope */
$([1,2,3,4,5]).each(function() {
var number = this;
$.getJSON("/values/" + number, function(data) {
sum += data.value;
done -= 1;
if(done == 0) $("#mynode").html(sum);
});
});
여러 AJAX 요청 병렬 실행
API를 사용하는 경우 여러 AJAX 요청을 서로 다른 엔드포인트에 발행해야 할 수 있습니다.jQuery를 사용하여 작업을 할 수 .$.when()★★★★
JS
$.when($.get('1.json'), $.get('2.json')).then(function(r1, r2){
console.log(r1[0].message + " " + r2[0].message);
});
콜백 함수는 이러한 GET 요구가 모두 정상적으로 종료되었을 때 실행됩니다. $.when() $.get()는 호출하여 새로운 약속 개체를 구축합니다.r1 ★★★★★★★★★★★★★★★★★」r2콜백 인수는 배열이며 첫 번째 요소는 서버 응답을 포함합니다.
여기 당신의 질문에 직접적으로 대답하려는 저의 시도가 있습니다.
기본적으로는 AJAX 콜스택을 구축하여 모두 실행하면 모든 이벤트가 완료되면 지정된 함수가 호출됩니다.제공된 인수는 제공된 모든 AJAX 요청의 결과 배열입니다.
확실히 이것은 초기 코드입니다.이것에 의해, 유연성의 관점에서 보다 상세하게 할 수 있습니다.
<script type="text/javascript" src="http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js"></script>
<script type="text/javascript">
var ParallelAjaxExecuter = function( onComplete )
{
this.requests = [];
this.results = [];
this.onComplete = onComplete;
}
ParallelAjaxExecuter.prototype.addRequest = function( method, url, data, format )
{
this.requests.push( {
"method" : method
, "url" : url
, "data" : data
, "format" : format
, "completed" : false
} )
}
ParallelAjaxExecuter.prototype.dispatchAll = function()
{
var self = this;
$.each( self.requests, function( i, request )
{
request.method( request.url, request.data, function( r )
{
return function( data )
{
console.log
r.completed = true;
self.results.push( data );
self.checkAndComplete();
}
}( request ) )
} )
}
ParallelAjaxExecuter.prototype.allRequestsCompleted = function()
{
var i = 0;
while ( request = this.requests[i++] )
{
if ( request.completed === false )
{
return false;
}
}
return true;
},
ParallelAjaxExecuter.prototype.checkAndComplete = function()
{
if ( this.allRequestsCompleted() )
{
this.onComplete( this.results );
}
}
var pe = new ParallelAjaxExecuter( function( results )
{
alert( eval( results.join( '+' ) ) );
} );
pe.addRequest( $.get, 'test.php', {n:1}, 'text' );
pe.addRequest( $.get, 'test.php', {n:2}, 'text' );
pe.addRequest( $.get, 'test.php', {n:3}, 'text' );
pe.addRequest( $.get, 'test.php', {n:4}, 'text' );
pe.dispatchAll();
</script>
여기 테스트가 있습니다.php
<?php
echo pow( $_GET['n'], 2 );
?>
업데이트: Yair Leviel의 답변에 따르면 이 답변은 쓸모 없습니다.jQuery와 같은 약속 라이브러리를 사용합니다.when() 또는 Q.js.
jQuery 확장자로 범용 솔루션을 만들었습니다.좀 더 일반적이게 미세조정이 필요하긴 하지만, 제 필요에 맞았습니다.이 기사의 시점에서는 이 기사에 기재되어 있는 다른 기법에 비해 이 기법의 장점은 콜백을 포함한 모든 유형의 비동기 처리를 사용할 수 있다는 것입니다.
주의: 클라이언트가 아직 다른 서드파티 라이브러리에 의존해도 괜찮다고 생각되면 이 대신 JavaScript용 Rx 확장을 사용합니다.
// jQuery extension for running multiple async methods in parallel
// and getting a callback with all results when all of them have completed.
//
// Each worker is a function that takes a callback as its only argument, and
// fires up an async process that calls this callback with its result.
//
// Example:
// $.parallel(
// function (callback) { $.get("form.htm", {}, callback, "html"); },
// function (callback) { $.post("data.aspx", {}, callback, "json"); },
// function (formHtml, dataJson) {
// // Handle success; each argument to this function is
// // the result of correlating ajax call above.
// }
// );
(function ($) {
$.parallel = function (anyNumberOfWorkers, allDoneCallback) {
var workers = [];
var workersCompleteCallback = null;
// To support any number of workers, use "arguments" variable to
// access function arguments rather than the names above.
var lastArgIndex = arguments.length - 1;
$.each(arguments, function (index) {
if (index == lastArgIndex) {
workersCompleteCallback = this;
} else {
workers.push({ fn: this, done: false, result: null });
}
});
// Short circuit this edge case
if (workers.length == 0) {
workersCompleteCallback();
return;
}
// Fire off each worker process, asking it to report back to onWorkerDone.
$.each(workers, function (workerIndex) {
var worker = this;
var callback = function () { onWorkerDone(worker, arguments); };
worker.fn(callback);
});
// Store results and update status as each item completes.
// The [0] on workerResultS below assumes the client only needs the first parameter
// passed into the return callback. This simplifies the handling in allDoneCallback,
// but may need to be removed if you need access to all parameters of the result.
// For example, $.post calls back with success(data, textStatus, XMLHttpRequest). If
// you need textStatus or XMLHttpRequest then pull off the [0] below.
function onWorkerDone(worker, workerResult) {
worker.done = true;
worker.result = workerResult[0]; // this is the [0] ref'd above.
var allResults = [];
for (var i = 0; i < workers.length; i++) {
if (!workers[i].done) return;
else allResults.push(workers[i].result);
}
workersCompleteCallback.apply(this, allResults);
}
};
})(jQuery);
업데이트 그리고 2년 후, 이것은 미친 것처럼 보입니다. 왜냐하면 받아들여진 답변이 훨씬 더 나은 것으로 바뀌었기 때문입니다. (하지만 여전히 jQuery를 사용한 Yair Leviel의 답변만큼 좋지 않습니다.)when)
오래된 를 리프레시하고 싶다.fadeOut후, 가 「」에 표시됩니다.fadeIn ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★」get새로운 콘텐츠입니다.fadeOut 및get비동기적이지만 연속적으로 실행하는 것은 시간 낭비입니다.
제가 하는 일은 재사용 가능한 기능의 형태를 제외하고는 인정된 답변과 동일합니다.이것의 주요 장점은 여기에 제시된 다른 제안보다 훨씬 짧다는 것이다.
var parallel = function(actions, finished) {
finishedCount = 0;
var results = [];
$.each(actions, function(i, action) {
action(function(result) {
results[i] = result;
finishedCount++;
if (finishedCount == actions.length) {
finished(results);
}
});
});
};
이치노각 기능은 결과를 전달하는 다른 기능을 수용해야 합니다(있는 경우). parallel을 사용하다
또한 모든 작업이 완료되면 호출되는 함수를 전달합니다.그러면 모든 결과가 포함된 어레이가 수신됩니다.예를 들면 다음과 같습니다.
refreshButton.click(function() {
parallel([
function(f) {
contentDiv.fadeOut(f);
},
function(f) {
portlet.content(f);
},
],
function(results) {
contentDiv.children().remove();
contentDiv.append(results[1]);
contentDiv.fadeIn();
});
});
새로 의 jQuery가 됩니다.fadeOut,이펙트.portlet.content(비동기)를 합니다).get 다 하고 두 결과(즉, 에 )를합니다.두 가지 작업이 모두 완료되면 오래된 콘텐츠를 삭제하고 두 번째 기능의 결과를 추가합니다.results[1] 및 )의 개요fadeIn새로운 콘텐츠입니다.
~로fadeOut 기능인 ' 기능되지 않습니다.results[0] 아도포포포포 presum presum presum presum presum를 포함하고 있을 것이다undefined그래서 무시해요., 그 「」에 .results어레이는 함수를 통과한 순서와 동일합니다.
당신은 이런 일을 할 수 있다.
var allData = []
$.getJSON("/values/1", function(data) {
allData.push(data);
if(data.length == 2){
processData(allData) // where process data processes all the data
}
});
$.getJSON("/values/2", function(data) {
allData.push(data);
if(data.length == 2){
processData(allData) // where process data processes all the data
}
});
var processData = function(data){
var sum = data[0] + data[1]
$('#mynode').html(sum);
}
다음은 mbostock/queue를 사용한 구현입니다.
queue()
.defer(function(callback) {
$.post('/echo/json/', {json: JSON.stringify({value: 1}), delay: 1}, function(data) {
callback(null, data.value);
});
})
.defer(function(callback) {
$.post('/echo/json/', {json: JSON.stringify({value: 3}), delay: 2}, function(data) {
callback(null, data.value);
});
})
.awaitAll(function(err, results) {
var result = results.reduce(function(acc, value) {
return acc + value;
}, 0);
console.log(result);
});
관련 바이올린: http://jsfiddle.net/MdbW2/
다음 확장 JQuery를 사용하여(스탠드 아론 함수로 쓸 수 있습니다).
$.whenAll({
val1: $.getJSON('/values/1'),
val2: $.getJSON('/values/2')
})
.done(function (results) {
var sum = results.val1.value + results.val2.value;
$('#mynode').html(sum);
});
All()의 경우 JQuery(1.x) 확장자:
$.whenAll = function (deferreds) {
function isPromise(fn) {
return fn && typeof fn.then === 'function' &&
String($.Deferred().then) === String(fn.then);
}
var d = $.Deferred(),
keys = Object.keys(deferreds),
args = keys.map(function (k) {
return $.Deferred(function (d) {
var fn = deferreds[k];
(isPromise(fn) ? fn : $.Deferred(fn))
.done(d.resolve)
.fail(function (err) { d.reject(err, k); })
;
});
});
$.when.apply(this, args)
.done(function () {
var resObj = {},
resArgs = Array.prototype.slice.call(arguments);
resArgs.forEach(function (v, i) { resObj[keys[i]] = v; });
d.resolve(resObj);
})
.fail(d.reject);
return d;
};
jsbin의 예를 참조해 주세요.http://jsbin.com/nuxuciwabu/edit?js,console
가장 전문적인 솔루션은 다음과 같이 async.js와 Array.reduce를 사용하는 것입니다.
async.map([1, 2, 3, 4, 5], function (number, callback) {
$.getJSON("/values/" + number, function (data) {
callback(null, data.value);
});
}, function (err, results) {
$("#mynode").html(results.reduce(function(previousValue, currentValue) {
return previousValue + currentValue;
}));
});
한 요청의 결과가 다른 요청에 따라 달라지면 병렬로 만들 수 없습니다.
Yair의 대답에 기반을 두고 있다.ajax 약속을 동적으로 정의할 수 있습니다.
var start = 1; // starting value
var len = 2; // no. of requests
var promises = (new Array(len)).fill().map(function() {
return $.ajax("/values/" + i++);
});
$.when.apply($, promises)
.then(myFunc, myFailure);
파일 이름의 배열이 있다고 가정합니다.
var templateNameArray=["test.html","test2.html","test3.html"];
htmlTemplatesLoadStateMap={};
var deffereds=[];
for (var i = 0; i < templateNameArray.length; i++)
{
if (!htmlTemplatesLoadStateMap[templateNameArray[i]])
{
deferreds.push($.get("./Content/templates/" +templateNameArray[i],
function (response, status, xhr) {
if (status == "error") { }
else {
$("body").append(response);
}
}));
htmlTemplatesLoadStateMap[templateNameArray[i]] = true;
}
}
$.when.all(deferreds).always(function(resultsArray) { yourfunctionTobeExecuted(yourPayload);
});
여러 개의 병렬 에이잭스 콜이 필요했고$.when구문은 완전히 받아들일 수 없었다$.ajax익숙한 형식입니다.그래서 제가 만든 건setInterval타이머를 사용하여 각 Ajax 콜이 언제 반환되었는지 정기적으로 확인합니다.일단 그것들이 모두 돌아오면, 나는 거기서부터 계속할 수 있다.
한 번에 실행할 수 있는Ajax 콜의 수에 브라우저 제한이 있을 수 있습니다(2)..$ajax는 본질적으로 비동기적이기 때문에 ajax 콜을 1개씩 작성하면 (브라우저의 제한 범위 내에서) 병렬 실행이 됩니다.
언급URL : https://stackoverflow.com/questions/1060539/parallel-asynchronous-ajax-requests-using-jquery
'programing' 카테고리의 다른 글
| Swift: 구조를 JSON으로 변환하시겠습니까? (0) | 2023.03.11 |
|---|---|
| MongoDB에 대한 '데이터 손실' 비판은 어느 정도 유효합니까? (0) | 2023.03.11 |
| 몽구스:CastError: 경로 "_id"에서 값 "개체 개체"에 대해 ObjectId로 캐스팅하지 못했습니다. (0) | 2023.03.11 |
| ASP.NET MVC: 레이저 뷰에서 컨트롤러 액션 메서드를 호출할 수 있는 모든 방법 (0) | 2023.03.11 |
| ng-app 지시어 배치(html vs body) (0) | 2023.03.11 |