지연된 jQuery는 어떻게 사용할 수 있습니까?
jQuery 1.5는 새로운 Deferred 객체와 연결된 메서드및 을 가져옵니다.
하지 않으신 분들을 위해.Deferred
그 출처에 주석을 달았습니다.
이 새로운 방법의 사용법은 어떤 것이 있을까요?패턴에 어떻게 맞출 수 있을까요?
API와 소스를 이미 읽었기 때문에 어떤 기능을 하는지 알 수 있습니다.궁금한 점은 일상 코드에서 이러한 새로운 기능을 어떻게 사용할 수 있는가 하는 것입니다.
AJAX 요청을 순서대로 호출하는 버퍼 클래스의 간단한 예를 보여 줍니다(다음은 이전 요청이 완료된 후 시작됩니다).
/* Class: Buffer
* methods: append
*
* Constructor: takes a function which will be the task handler to be called
*
* .append appends a task to the buffer. Buffer will only call a task when the
* previous task has finished
*/
var Buffer = function(handler) {
var tasks = [];
// empty resolved deferred object
var deferred = $.when();
// handle the next object
function handleNextTask() {
// if the current deferred task has resolved and there are more tasks
if (deferred.isResolved() && tasks.length > 0) {
// grab a task
var task = tasks.shift();
// set the deferred to be deferred returned from the handler
deferred = handler(task);
// if its not a deferred object then set it to be an empty deferred object
if (!(deferred && deferred.promise)) {
deferred = $.when();
}
// if we have tasks left then handle the next one when the current one
// is done.
if (tasks.length > 0) {
deferred.done(handleNextTask);
}
}
}
// appends a task.
this.append = function(task) {
// add to the array
tasks.push(task);
// handle the next task
handleNextTask();
};
};
의 데모와 가능한 용도를 찾고 있습니다..Deferred
★★★★★★★★★★★★★★★★★」.when
.
예를 ,, 의, 의, 의, of, of, of, of, of, of, of, of, of, of, of, of, of, of, of, of,._Deferred
.
예를 들어 새로운 소스에 링크하는 것은 부정행위입니다.
저는 특히 작업이 동기식인지 비동기식인지를 추상화할 때 어떤 기술을 사용할 수 있는지 관심이 있습니다.
가장 좋은 사용 사례는 AJAX 응답을 캐싱하는 것입니다.이 주제에 관한 Rebecca Murphey의 도입부 투고에서 변경된 예를 다음에 제시하겠습니다.
var cache = {};
function getData( val ){
// return either the cached value or jqXHR object wrapped Promise
return $.when(
cache[ val ] ||
$.ajax('/foo/', {
data: { value: val },
dataType: 'json',
success: function( resp ){
cache[ val ] = resp;
}
})
);
}
getData('foo').then(function(resp){
// do something with the response, which may
// or may not have been retrieved using an
// XHR request.
});
기본적으로 캐시에서 즉시 반환되기 전에 값이 이미 한 번 요청된 경우.그렇지 않으면 AJAX 요청이 데이터를 가져와 캐시에 추가합니다.$.when
/.then
그냥 돼요,요.필요한 것은 응답의 사용뿐입니다.이 응답은 에 전달됩니다..then()
두 경우 모두 핸들러입니다.jQuery.when()
비약속/지연된 것을 완료로 처리하여 모든 것을 즉시 실행한다..done()
★★★★★★★★★★★★★★★★★」.then()
쇠사슬에 묶여서
지연은 작업이 비동기적으로 작동할 수도 있고 그렇지 않을 수도 있으며 코드로부터 해당 조건을 추상화하려는 경우에 적합합니다.
「 」를한 다른 실제 예.$.when
★★★★★★★★★★★★★★★★★★:
$.when($.getJSON('/some/data/'), $.get('template.tpl')).then(function (data, tmpl) {
$(tmpl) // create a jQuery object out of the template
.tmpl(data) // compile it
.appendTo("#target"); // insert it into the DOM
});
다음은 ehynd의 답변과 약간 다른 AJAX 캐시의 구현입니다.
Fortune Rice의 후속 질문에서 언급되었듯이, ehynd의 구현은 요청이 반환되기 전에 수행된 경우 여러 동일한 요청을 실제로 방지하지 못했습니다.그것은,
for (var i=0; i<3; i++) {
getData("xxx");
}
"xxx"에 대한 결과가 캐시되지 않은 경우 3개의 AJAX 요청이 발생할 가능성이 높습니다.
이 문제는 결과 대신 요청의 지연을 캐싱하여 해결할 수 있습니다.
var cache = {};
function getData( val ){
// Return a promise from the cache (if available)
// or create a new one (a jqXHR object) and store it in the cache.
var promise = cache[val];
if (!promise) {
promise = $.ajax('/foo/', {
data: { value: val },
dataType: 'json'
});
cache[val] = promise;
}
return promise;
}
$.when(getData('foo')).then(function(resp){
// do something with the response, which may
// or may not have been retreived using an
// XHR request.
});
뮤텍스 대신 지연을 사용할 수 있습니다.이는 기본적으로 여러 Ajax 사용 시나리오와 동일합니다.
뮤텍스
var mutex = 2;
setTimeout(function() {
callback();
}, 800);
setTimeout(function() {
callback();
}, 500);
function callback() {
if (--mutex === 0) {
//run code
}
}
지연되었다
function timeout(x) {
var dfd = jQuery.Deferred();
setTimeout(function() {
dfd.resolve();
}, x);
return dfd.promise();
}
jQuery.when(
timeout(800), timeout(500)).done(function() {
// run code
});
Deferred를 뮤텍스로만 사용하는 경우 퍼포먼스에 영향을 주지 않도록 주의하십시오(http://jsperf.com/deferred-vs-mutex/2)이연에 의해 제공되는 편리함과 더불어 추가적인 이점을 충분히 누릴 수 있지만, 실제(사용자 주도 이벤트 기반) 사용에서는 성능에 미치는 영향이 눈에 띄지 않습니다.
이것은 자기 홍보적인 답변이지만, 저는 몇 달 동안 이것을 연구하여 jQuery Conference San Francisco 2012에서 결과를 발표했습니다.
다음은 강연의 무료 비디오입니다.
https://www.youtube.com/watch?v=juRtEEsHI9E
또 다른 좋은 용도로는 여러 소스에서 데이터를 가져오는 것입니다.다음 예제에서는 클라이언트와 REST 서버 간의 검증을 위해 기존 응용 프로그램에서 사용되는 여러 개의 독립적인 JSON 스키마 개체를 가져옵니다.이 경우 브라우저 측 응용 프로그램이 모든 스키마를 로드하기 전에 데이터 로드를 시작하지 않도록 합니다.이 경우 $.when.sween.sween()이 적합합니다.그때(fn1, fn2)를 사용하여 오류 상태를 모니터링하기 위한 포인터에 대해 Raynos에게 감사합니다.
fetch_sources = function (schema_urls) {
var fetch_one = function (url) {
return $.ajax({
url: url,
data: {},
contentType: "application/json; charset=utf-8",
dataType: "json",
});
}
return $.map(schema_urls, fetch_one);
}
var promises = fetch_sources(data['schemas']);
$.when.apply(null, promises).then(
function () {
var schemas = $.map(arguments, function (a) {
return a[0]
});
start_application(schemas);
}, function () {
console.log("FAIL", this, arguments);
});
다른 에서는 '보다 낫다'를 사용하기도 합니다.Deferred
모든 종류의 계산(일반적으로 퍼포먼스 집약적인 태스크 또는 장기 실행 태스크)에 대해 캐시를 구현합니다.
var ResultsCache = function(computationFunction, cacheKeyGenerator) {
this._cache = {};
this._computationFunction = computationFunction;
if (cacheKeyGenerator)
this._cacheKeyGenerator = cacheKeyGenerator;
};
ResultsCache.prototype.compute = function() {
// try to retrieve computation from cache
var cacheKey = this._cacheKeyGenerator.apply(this, arguments);
var promise = this._cache[cacheKey];
// if not yet cached: start computation and store promise in cache
if (!promise) {
var deferred = $.Deferred();
promise = deferred.promise();
this._cache[cacheKey] = promise;
// perform the computation
var args = Array.prototype.slice.call(arguments);
args.push(deferred.resolve);
this._computationFunction.apply(null, args);
}
return promise;
};
// Default cache key generator (works with Booleans, Strings, Numbers and Dates)
// You will need to create your own key generator if you work with Arrays etc.
ResultsCache.prototype._cacheKeyGenerator = function(args) {
return Array.prototype.slice.call(arguments).join("|");
};
다음으로 이 클래스를 사용하여 (시뮬레이션된 헤비) 계산을 수행하는 예를 나타냅니다.
// The addingMachine will add two numbers
var addingMachine = new ResultsCache(function(a, b, resultHandler) {
console.log("Performing computation: adding " + a + " and " + b);
// simulate rather long calculation time by using a 1s timeout
setTimeout(function() {
var result = a + b;
resultHandler(result);
}, 1000);
});
addingMachine.compute(2, 4).then(function(result) {
console.log("result: " + result);
});
addingMachine.compute(1, 1).then(function(result) {
console.log("result: " + result);
});
// cached result will be used
addingMachine.compute(2, 4).then(function(result) {
console.log("result: " + result);
});
Ajax 요청을 캐시하는 데 동일한 기본 캐시를 사용할 수 있습니다.
var ajaxCache = new ResultsCache(function(id, resultHandler) {
console.log("Performing Ajax request for id '" + id + "'");
$.getJSON('http://jsfiddle.net/echo/jsonp/?callback=?', {value: id}, function(data) {
resultHandler(data.value);
});
});
ajaxCache.compute("anID").then(function(result) {
console.log("result: " + result);
});
ajaxCache.compute("anotherID").then(function(result) {
console.log("result: " + result);
});
// cached result will be used
ajaxCache.compute("anID").then(function(result) {
console.log("result: " + result);
});
이 jsFiddle에서는 위의 코드를 사용할 수 있습니다.
1) 콜백을 순서대로 실행하기 위해 사용합니다.
var step1 = new Deferred();
var step2 = new Deferred().done(function() { return step1 });
var step3 = new Deferred().done(function() { return step2 });
step1.done(function() { alert("Step 1") });
step2.done(function() { alert("Step 2") });
step3.done(function() { alert("All done") });
//now the 3 alerts will also be fired in order of 1,2,3
//no matter which Deferred gets resolved first.
step2.resolve();
step3.resolve();
step1.resolve();
2) 앱 상태를 확인하기 위해 사용합니다.
var loggedIn = logUserInNow(); //deferred
var databaseReady = openDatabaseNow(); //deferred
jQuery.when(loggedIn, databaseReady).then(function() {
//do something
});
지연 객체를 사용하여 웹킷 브라우저에서 잘 작동하는 유동적인 설계를 만들 수 있습니다.FF 및 IE가 크기 조정마다 이벤트를 한 번만 실행하는 것과 달리, 웹킷 브라우저는 크기가 조정되는 픽셀마다 크기 조정 이벤트를 실행합니다.따라서 창 크기 조정 이벤트에 바인딩된 함수의 실행 순서를 제어할 수 없습니다.다음과 같은 방법으로 문제를 해결합니다.
var resizeQueue = new $.Deferred(); //new is optional but it sure is descriptive
resizeQueue.resolve();
function resizeAlgorithm() {
//some resize code here
}
$(window).resize(function() {
resizeQueue.done(resizeAlgorithm);
});
그러면 의도한 대로 실행되도록 코드 실행이 직렬화됩니다.오브젝트 메서드를 보류된 콜백으로 전달할 때는 함정에 주의하십시오.이러한 메서드가 지연에 대한 콜백으로 실행되면 'this' 참조는 지연된 오브젝트에 대해 덮어쓰며 메서드가 속한 오브젝트를 더 이상 참조하지 않습니다.
JQuery를 사용하는 서드파티 라이브러리와 통합할 수도 있습니다.
이러한 라이브러리의 하나는 Backbone으로, 실제로는 다음 버전에서 Deferred를 지원할 예정입니다.
방금 실제 코드에서 Delferred를 사용했습니다.프로젝트 jQuery Terminal에서는 사용자가 정의한 명령어를 호출하는 함수 exec이 있습니다(예를 들어 사용자가 명령어를 입력하고 Enter 키를 누르는 경우). API에 지연을 추가하고 어레이를 사용하여 exec을 호출합니다.다음과 같습니다.
terminal.exec('command').then(function() {
terminal.echo('command finished');
});
또는
terminal.exec(['command 1', 'command 2', 'command 3']).then(function() {
terminal.echo('all commands finished');
});
명령어는 비동기 코드를 실행할 수 있으며, EXEC은 사용자 코드를 순서대로 호출해야 합니다.나의 첫 번째 API는 일시정지/재개 호출 쌍을 사용하며, 새로운 API에서는 사용자가 약속을 반환할 때 자동으로 호출합니다.그래서 사용자 코드는
return $.get('/some/url');
또는
var d = new $.Deferred();
setTimeout(function() {
d.resolve("Hello Deferred"); // resolve value will be echoed
}, 500);
return d.promise();
코드를 다음과 같이 사용합니다.
exec: function(command, silent, deferred) {
var d;
if ($.isArray(command)) {
return $.when.apply($, $.map(command, function(command) {
return self.exec(command, silent);
}));
}
// both commands executed here (resume will call Term::exec)
if (paused) {
// delay command multiple time
d = deferred || new $.Deferred();
dalyed_commands.push([command, silent, d]);
return d.promise();
} else {
// commands may return promise from user code
// it will resolve exec promise when user promise
// is resolved
var ret = commands(command, silent, true, deferred);
if (!ret) {
if (deferred) {
deferred.resolve(self);
return deferred.promise();
} else {
d = new $.Deferred();
ret = d.promise();
ret.resolve();
}
}
return ret;
}
},
dalyed_module은 모든 dalyed_module을 사용하여 exec을 다시 호출하는 재개 함수로 사용됩니다.
명령어의 일부가 기능합니다(관련되지 않은 부분을 제거했습니다).
function commands(command, silent, exec, deferred) {
var position = lines.length-1;
// Call user interpreter function
var result = interpreter.interpreter(command, self);
// user code can return a promise
if (result != undefined) {
// new API - auto pause/resume when using promises
self.pause();
return $.when(result).then(function(result) {
// don't echo result if user echo something
if (result && position === lines.length-1) {
display_object(result);
}
// resolve promise from exec. This will fire
// code if used terminal::exec('command').then
if (deferred) {
deferred.resolve();
}
self.resume();
});
}
// this is old API
// if command call pause - wait until resume
if (paused) {
self.bind('resume.command', function() {
// exec with resume/pause in user code
if (deferred) {
deferred.resolve();
}
self.unbind('resume.command');
});
} else {
// this should not happen
if (deferred) {
deferred.resolve();
}
}
}
ehynds의 응답은 응답 데이터를 캐시하기 때문에 작동하지 않습니다.약속이기도 한 jqXHR을 캐시해야 합니다.다음은 올바른 코드입니다.
var cache = {};
function getData( val ){
// return either the cached value or an
// jqXHR object (which contains a promise)
return cache[ val ] || $.ajax('/foo/', {
data: { value: val },
dataType: 'json',
success: function(data, textStatus, jqXHR){
cache[ val ] = jqXHR;
}
});
}
getData('foo').then(function(resp){
// do something with the response, which may
// or may not have been retreived using an
// XHR request.
});
Julian D.의 답변은 정확하고 더 나은 해결책이 될 것입니다.
언급URL : https://stackoverflow.com/questions/4869609/how-can-jquery-deferred-be-used
'programing' 카테고리의 다른 글
PHP 배열 삭제 값(키 아님) (0) | 2022.12.31 |
---|---|
MySQL SELECT LIKE 또는 REGEXP를 사용하여 하나의 레코드에서 여러 단어를 일치시킵니다. (0) | 2022.12.31 |
autoconf를 찾을 수 없습니다.autoconf 설치 Xampp를 Cent로 확인하십시오.OS (0) | 2022.12.31 |
JavaScript 또는 디버깅에서 DOM 노드에서 이벤트 청취자를 찾는 방법은 무엇입니까? (0) | 2022.12.31 |
앰퍼샌드를 사용하여 PHP 함수를 시작하는 것은 무엇을 의미합니까? (0) | 2022.12.31 |