jQuery 지연 및 약속에 대해 읽었 으며 성공적인 콜백에 .then()
& .done()
를 사용하는 것의 차이점을 볼 수 없습니다 . 나도 에릭 Hynds는 것을 언급 .done()
과 .success()
같은 기능에 매핑 그러나 나는 그렇게 추측하고있어 .then()
모든 콜백 모든 성공적인 작업의 완료에 호출한다.
누구든지 올바른 사용법을 가르쳐 줄 수 있습니까?
jQuery 지연 및 약속에 대해 읽었 으며 성공적인 콜백에 .then()
& .done()
를 사용하는 것의 차이점을 볼 수 없습니다 . 나도 에릭 Hynds는 것을 언급 .done()
과 .success()
같은 기능에 매핑 그러나 나는 그렇게 추측하고있어 .then()
모든 콜백 모든 성공적인 작업의 완료에 호출한다.
누구든지 올바른 사용법을 가르쳐 줄 수 있습니까?
답변:
done()
연기 된 문제가 해결되면 연결된 콜백이 시작 됩니다. fail()
지연된 항목이 거부되면 연결된 콜백이 시작 됩니다.
jQuery 1.8 이전에는 then()
구문 설탕이었습니다.
promise.then( doneCallback, failCallback )
// was equivalent to
promise.done( doneCallback ).fail( failCallback )
1.8부터는 새로운 약속 then()
의 별칭 pipe()
이며 반환합니다 . 에 대한 자세한 내용 은 여기 를 참조 하십시오pipe()
.
success()
그리고 error()
온에서만 사용할 수 있습니다 jqXHR
호출에 의해 반환 된 객체 ajax()
. 그들은을위한 간단한 별칭 done()
과 fail()
각각 :
jqXHR.done === jqXHR.success
jqXHR.fail === jqXHR.error
또한 done()
단일 콜백으로 제한되지 않으며 비 기능을 필터링합니다 (버전 1.8의 문자열에 1.8.1에서 수정해야하는 버그가 있음).
// this will add fn1 to 7 to the deferred's internal callback list
// (true, 56 and "omg" will be ignored)
promise.done( fn1, fn2, true, [ fn3, [ fn4, 56, fn5 ], "omg", fn6 ], fn7 );
동일합니다 fail()
.
then
새로운 약속을 돌려주는 것은 내가 놓친 핵심이었습니다. 왜 같은 체인 $.get(....).done(function(data1) { return $.get(...) }).done(function(data2) { ... })
이 data2
정의되지 않은 채 실패 했는지 이해할 수 없었습니다 . 원래 약속에 더 많은 처리기를 연결하는 대신 약속을 함께 파이프하기를 원했기 때문에 변경 done
으로 then
인해 효과가있었습니다.
done
나 then
? 왜?
반환 결과가 처리되는 방식에도 차이가 있습니다 (연결이라고 함, 연결 done
하지 않고 then
호출 체인 을 생성 함)
promise.then(function (x) { // Suppose promise returns "abc"
console.log(x);
return 123;
}).then(function (x){
console.log(x);
}).then(function (x){
console.log(x)
})
다음과 같은 결과가 기록됩니다.
abc
123
undefined
동안
promise.done(function (x) { // Suppose promise returns "abc"
console.log(x);
return 123;
}).done(function (x){
console.log(x);
}).done(function (x){
console.log(x)
})
다음을 얻을 것이다 :
abc
abc
abc
---------- 업데이트 :
Btw. 원자 유형 값 대신 Promise를 반환하면 외부 약속이 내부 약속이 해결 될 때까지 기다립니다.
promise.then(function (x) { // Suppose promise returns "abc"
console.log(x);
return $http.get('/some/data').then(function (result) {
console.log(result); // suppose result === "xyz"
return result;
});
}).then(function (result){
console.log(result); // result === xyz
}).then(function (und){
console.log(und) // und === undefined, because of absence of return statement in above then
})
이러한 방식으로 다음과 같은 병렬 또는 순차적 비동기 작업을 작성하는 것이 매우 간단 해집니다.
// Parallel http requests
promise.then(function (x) { // Suppose promise returns "abc"
console.log(x);
var promise1 = $http.get('/some/data?value=xyz').then(function (result) {
console.log(result); // suppose result === "xyz"
return result;
});
var promise2 = $http.get('/some/data?value=uvm').then(function (result) {
console.log(result); // suppose result === "uvm"
return result;
});
return promise1.then(function (result1) {
return promise2.then(function (result2) {
return { result1: result1, result2: result2; }
});
});
}).then(function (result){
console.log(result); // result === { result1: 'xyz', result2: 'uvm' }
}).then(function (und){
console.log(und) // und === undefined, because of absence of return statement in above then
})
위의 코드는 두 개의 http 요청을 병렬로 발행하여 요청을 더 빨리 완료하는 반면, http 요청 아래에서 순차적으로 실행되므로 서버로드가 줄어 듭니다.
// Sequential http requests
promise.then(function (x) { // Suppose promise returns "abc"
console.log(x);
return $http.get('/some/data?value=xyz').then(function (result1) {
console.log(result1); // suppose result1 === "xyz"
return $http.get('/some/data?value=uvm').then(function (result2) {
console.log(result2); // suppose result2 === "uvm"
return { result1: result1, result2: result2; };
});
});
}).then(function (result){
console.log(result); // result === { result1: 'xyz', result2: 'uvm' }
}).then(function (und){
console.log(und) // und === undefined, because of absence of return statement in above then
})
done
결과가 then
바뀌는 결과에 아무런 영향을 미치지 않는 개념에 +1 . 다른 사람들이 놓친 거대한 점.
then
1.8 변경
done
예제 와 동일하게 작동합니다 . 변화 then
에 pipe
의 사전 1.8은 1.8 이상받을 then
행동을.
.done()
콜백이 하나 뿐이며 성공 콜백입니다.
.then()
성공과 실패 콜백이 모두 있습니다
.fail()
하나의 실패 콜백이 있습니다
그래서 당신이해야 할 일은 당신에게 달려 있습니다 ... 성공했는지 아니면 실패하는지 걱정하십니까?
then()
다릅니다 done()
. 로 then()
자주 / 기억 알 수있는 중요한 것은보다 상세하게는 만 포인트 콜백 성공으로 오히려입니다라고합니다. (jQuery 3.0 이전의 상황을 말할 수 없음)
Deferred가 해결 될 때만 호출 할 핸들러를 추가합니다 . 호출 할 콜백을 여러 개 추가 할 수 있습니다.
var url = 'http://jsonplaceholder.typicode.com/posts/1';
$.ajax(url).done(doneCallback);
function doneCallback(result) {
console.log('Result 1 ' + result);
}
위와 같이 쓸 수도 있습니다.
function ajaxCall() {
var url = 'http://jsonplaceholder.typicode.com/posts/1';
return $.ajax(url);
}
$.when(ajaxCall()).then(doneCallback, failCallback);
Deferred가 해결, 거부 또는 여전히 진행 중일 때 호출 될 핸들러를 추가합니다 .
var url = 'http://jsonplaceholder.typicode.com/posts/1';
$.ajax(url).then(doneCallback, failCallback);
function doneCallback(result) {
console.log('Result ' + result);
}
function failCallback(result) {
console.log('Result ' + result);
}
then
경우) 게시물이 명확하지 않습니다.fail
fail
jQuery의 Deferreds가 Promises의 구현으로 간주되는 한 (jQuery3.0은 실제로 스펙을 적용하려고 시도하는 한) 실제로 중요한 차이가 있습니다.
done / then의 주요 차이점은
.done()
항상 자신이 무엇을하든, 무엇을 반환하든 관계없이 항상 같은 약속 / 포장 값을 반환합니다. .then()
항상 새 약속을 반환하며, 전달한 함수에 따라 약속의 내용을 제어 할 책임이 있습니다. jQuery에서 기본 ES2015 Promises로 변환되는 .done()
것은 체인이 "해결"상태 인 경우 값이 함수에 전달된다는 점에서 Promise 체인의 함수 주위에 "탭"구조를 구현하는 것과 비슷합니다. 그러나 그 기능의 결과는 체인 자체에 영향을 미치지 않습니다.
const doneWrap = fn => x => { fn(x); return x };
Promise.resolve(5)
.then(doneWrap( x => x + 1))
.then(doneWrap(console.log.bind(console)));
$.Deferred().resolve(5)
.done(x => x + 1)
.done(console.log.bind(console));
6이 아닌 5를 기록합니다.
나는 done과 doneWrap을 사용하여 로깅을 수행했다. console.log 함수는 실제로 아무것도 반환하지 않기 때문입니다. 그리고 아무것도 반환하지 않는 함수를 전달하면 어떻게됩니까?
Promise.resolve(5)
.then(doneWrap( x => x + 1))
.then(console.log.bind(console))
.then(console.log.bind(console));
그것은 기록 할 것이다 :
5
찾으시는 주소가 없습니다
어떻게 된 거예요? .then을 사용하고 아무것도 반환하지 않는 함수를 전달했을 때 암시적인 결과는 "정의되지 않음"이었습니다. 물론 다음 정의 된 Promise [undefined]를 다음 then 메소드에 반환하여 undefined를 기록했습니다. 우리가 시작한 원래 가치는 기본적으로 없어졌습니다.
.then()
핵심은 함수 구성의 형태입니다. 각 단계의 결과는 다음 단계에서 함수의 인수로 사용됩니다. .done이 "탭"으로 가장 잘 생각되는 이유입니다.-> 실제로 컴포지션의 일부가 아니며 특정 단계에서 값을 들여다보고 해당 값에서 함수를 실행하지만 실제로는 변경하지 않는 것입니다. 어떤 식 으로든 구성.
이것은 근본적인 차이점이며, 기본 약속에 .done 메서드가 구현되어 있지 않은 좋은 이유가 있습니다. 우리는 왜 더 .fail 메소드가 없는지 알아낼 필요가 없습니다. 왜냐하면 .fail / .catch는 더 복잡하기 때문입니다 (즉, .fail / .catch는 베어 값을 반환하는 .dach / .then-> 함수의 미러가 아닙니다 "체재"는.
then()
항상 어떤 경우에도 호출됩니다. 그러나 매개 변수 전달은 jQuery 버전마다 다릅니다.
jQuery를 1.8 이전에, then()
동일done().fail()
. 그리고 모든 콜백 함수는 동일한 매개 변수를 공유합니다.
그러나 jQuery 1.8부터 then()
부터는 새로운 약속을 반환하고 값을 반환하면 다음 콜백 함수로 전달됩니다.
다음 예제를 보자.
var defer = jQuery.Deferred();
defer.done(function(a, b){
return a + b;
}).done(function( result ) {
console.log("result = " + result);
}).then(function( a, b ) {
return a + b;
}).done(function( result ) {
console.log("result = " + result);
}).then(function( a, b ) {
return a + b;
}).done(function( result ) {
console.log("result = " + result);
});
defer.resolve( 3, 4 );
jQuery 1.8 이전에 답은
result = 3
result = 3
result = 3
모두 result
3이 걸립니다. 그리고then()
함수는 항상 다음 함수 같은 연기 객체를 전달합니다.
그러나 jQuery 1.8 기준으로 결과는 다음과 같아야합니다.
result = 3
result = 7
result = NaN
첫 번째 then()
함수는 새로운 promise를 반환하고 값 7 (및 전달할 유일한 매개 변수)이 다음으로 전달 done()
되므로 두 번째 done()
write result = 7
입니다. 두 번째 then()
값은 7을 값으로 사용 a
하고 두 번째 undefined
값은 NaN 매개 변수를 사용하여 새 약속을 반환하고 마지막 은 NaN을 결과로 인쇄합니다.b
then()
done()
jQuery.Deferred()
가 여러 값을 수신 할 수 있다는 흥미로운 측면 은 첫 번째 값으로 올바르게 전달 .then()
됩니다 .—하지만 조금 이상하지만 ... 다음과 같이 .then()
할 수 없습니다. (선택된 인터페이스를 통해 return
하나의 값만 반환 할 수 있습니다.) Javascript의 기본 Promise
은 그렇게하지 않습니다. (정직하게 말하면 더 일관성이 있습니다.)
.then()
이것의 단점은 .done()
resolve()
호출 (모든 .done()
핸들러는 동기식으로 실행 됨)resolve()
등록 된 .done()
처리기 에서 예외가 발생할 수 있습니다 (!).done()
유예 자의 절반을 죽이는 예외 :
.done()
처리기는 자동으로 건너 뜁니다.나는 예외가 자동으로 무시되지 않도록 .then(oneArgOnly)
항상 필요 하다고 생각 .catch()
했지만 더 이상 사실이 아닙니다. unhandledrejection
이벤트 .then()
는 콘솔에서 처리되지 않은 예외를 콘솔에 기록 합니다 (기본값). 매우 합리적입니다! 전혀 사용할 이유가 없습니다 .done()
.
다음 코드 스 니펫은 다음을 보여줍니다.
.done()
핸들러는 시점에서 동기식으로 호출됩니다.resolve()
.done()
영향 resolve()
발신자의
예외resolve()
.done()
해결로
약속을 깰.then()
이 문제들 중 어느 것도 없다
unhandledrejection
것 같습니다)Btw의 예외를 .done()
제대로 포착 할 수 없습니다 :의 동기 패턴으로 인해 (라이브러리 코드 일 수 있습니다!) 지연되거나 지연된 이체가 이미 해결 된 경우 범인을 첨부하는 호출 에서 .done()
오류가 발생합니다 ..resolve()
.done()
console.log('Start of script.');
let deferred = $.Deferred();
// deferred.resolve('Redemption.');
deferred.fail(() => console.log('fail()'));
deferred.catch(()=> console.log('catch()'));
deferred.done(() => console.log('1-done()'));
deferred.then(() => console.log('2-then()'));
deferred.done(() => console.log('3-done()'));
deferred.then(() =>{console.log('4-then()-throw');
throw 'thrown from 4-then()';});
deferred.done(() => console.log('5-done()'));
deferred.then(() => console.log('6-then()'));
deferred.done(() =>{console.log('7-done()-throw');
throw 'thrown from 7-done()';});
deferred.done(() => console.log('8-done()'));
deferred.then(() => console.log('9-then()'));
console.log('Resolving.');
try {
deferred.resolve('Solution.');
} catch(e) {
console.log(`Caught exception from handler
in resolve():`, e);
}
deferred.done(() => console.log('10-done()'));
deferred.then(() => console.log('11-then()'));
console.log('End of script.');
<script
src="https://code.jquery.com/jquery-3.4.1.min.js"
integrity="sha384-vk5WoKIaW/vJyUAd9n/wmopsmNhiy+L2Z+SBxGYnUkunIxVxAv/UtMOhba/xskxh"
crossorigin="anonymous"
></script>
done
이전에 예외가있는 경우 실행되지 않을 것을 말하고 있습니다. 그러나 왜 자동으로 무시됩니까? 예외가 발생했기 때문에 왜 침묵한다고 말합니까? 2)Deferred
API가 매우 잘못 수행 되어 객체를 멸시합니다 . 너무 복잡하고 혼란 스럽다. 여기에있는 코드는 요점을 증명하는 데 도움이되지 않으며 증명하려는 내용에 너무 많은 불필요한 복잡성이 있습니다. 3)done
at 인덱스 2, 4 및 6 이 왜 2 차 전에 수행 then
됩니까?
.then()
예외가 발생했는지 여부에 관계없이 모두 호출됩니다. 그러나 추가 / 남은 .done()
휴식.
jQuery 3.0 과 비교할 때 예기치 않은 동작으로 이어질 수 있으며 이전 답변에서 언급되지 않은 중요한 차이점이 하나 더 있습니다.
다음 코드를 고려하십시오.
let d = $.Deferred();
d.done(() => console.log('then'));
d.resolve();
console.log('now');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
이것은 출력됩니다 :
then
now
이제, 교체 done()
가 then()
바로 그 조각에서 :
var d = $.Deferred();
d.then(() => console.log('then'));
d.resolve();
console.log('now');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
출력은 다음과 같습니다.
now
then
따라서 즉시 해결 된 지연의 경우 전달 된 함수 done()
는 항상 동기 방식으로 호출되는 반면 전달 된 인수 then()
는 비동기 적으로 호출됩니다.
이것은 업그레이드 가이드에 언급 된 것처럼 두 콜백이 동 기적으로 호출되는 이전 jQuery 버전과 다릅니다 .
Promises / A + 준수에 필요한 또 다른 동작 변경은 Deferred .then () 콜백이 항상 비동기 적으로 호출된다는 것입니다. 이전에는 .then () 콜백이 이미 해결되었거나 거부 된 지연에 추가 된 경우 콜백은 즉시 동기식으로 실행되었습니다.
.done()
약속 체인을 종료하여 추가 단계를 수행 할 수있는 것은 없습니다. 이것은 아무도 jQuery promise 구현이 처리 할 수없는 예외를 던질 수 있음을 의미합니다. 아무도이를 사용하여 처리 할 수 없기 때문 .fail()
입니다.
실제로 약속에 더 많은 단계를 첨부하지 않으려면을 사용해야합니다 .done()
. 자세한 내용은 약속을해야하는 이유를 참조하십시오
.done()
종료 역할이 없는 jQuery에는 적합 하지 않습니다. 문서에 따르면 "deferred.done ()이 지연된 객체를 반환하므로 추가 .done () 메서드를 포함하여 지연된 객체의 다른 메서드를이 메서드에 연결할 수 있습니다". .fail()
언급되지 않았지만 그렇습니다.