https://www.zerocho.com/category/jQuery/post/57c90814addc111500d85a19
0389c7d2078865a73f345b23153c49fe
안녕하세요. 이번 시간에는 제이쿼리의 프로미스 기능과 deferred 객체에 대해 알아보겠습니다. 지난 AJAX 시간에도 살짝 다뤘는데요. 프로미스를 사용하면 비동기 프로그래밍을 할 때 코드를 간결하게 관리할 수 있습니다.
제이쿼리 프로미스는 기본적으로 공식 구현을 따르지 않아서 문제가 있습니다. 에러 처리와 프로미스 실행 순서에 관한 문제입니다. 하지만 복잡한 프로미스를 구현하지 않는 이상은 그 문제가 발생하지 않기 때문에 그냥 사용하셔도 됩니다. (제이쿼리 3.0에서는 그 문제가 해결되었습니다)
제이쿼리는 프로미스를 사용할 수 있게 Deferred라는 객체를 제공합니다. 이 객체를 사용하면 일반 코드도 프로미스처럼 사용할 수 있습니다.
일단 제이쿼리 프로미스의 기본 구조는 프로미스 객체가 완료되었을 때 done 메소드가 호출되고 실패했을 때는 fail, 완료되었건 실패했건 행동이 끝났으면 always가 호출됩니다. 아주 오래 걸리고 복잡한 함수가 다음과 같이 있다고 가정해봅시다.
var longAndComplicatedFunction = function() {
try {
// 완료되려면 50초가 걸리는 매우 복잡한 코드
console.log('성공');
} catch (err) {
console.log('실패');
}
};
longAndComplicatedFunction();
console.log('다음 행동');
이렇게 복잡한 코드가 있으면 이 코드를 실행하는 50초 동안은 아무 것도 할 수 없습니다. 50초 후에야 다음 행동이 실행될 겁니다. 사용자들은 멍하니 기다리거나 화가 나서 앱을 종료할 겁니다.
이렇 때 비동기 프로그래밍이 필요합니다. 흔히 콜백 형식이나 프로미스 형식을 사용하는 데, 콜백 형식은 점점 더 코드가 복잡해지는 문제를 발생시키기 때문에, 콜백이 여러 번 중첩될 것 같으면 프로미스 형식을 사용해야합니다. 다음과 같이 위의 코드를 바꿔봅시다.
var longAndComplicatedFunction = function() {
var deferred = $.Deferred();
try {
// 완료되려면 50초가 걸리는 매우 복잡한 비동기 코드
deferred.resolve('성공');
} catch (err) {
deferred.reject(err);
}
return deferred.promise();
};
longAndComplicatedFunction().done(function(message) {
console.log(message);
}).fail(function(error) {
console.log(error);
}).always(function() {
console.log('완료!');
});
console.log('다음 행동');
이렇게 $.Deferred()
로 deferred 객체를 만들고, 성공했을 때에는 resolve, 실패했을 때에는 reject 메소드를 호출하면 resolve는 done으로, reject는 fail로 연결됩니다.
이제 비동기 방식으로 했기 때문에 다음 행동은 50초를 기다릴 필요 없이 바로 실행되고, 복잡한 행동이 완료되었을 시 등록해둔 done 메소드가 실행됩니다. 실패했다면 fail 메소드가 실행되고요. longAndComplicatedFunction 함수에서 deferred.promise()
를 return하는 것을 잊지 마세요!
참고로 done이나 fail로 구분하지 않고 한 번에 처리하려면 then 메소드가 있습니다. 첫 번째 인자는 성공 시 콜백이고, 두 번째 인자는 실패 시 콜백입니다. then도 연달아 쓸 수 있습니다.
longAndComplicatedFunction().then(function(message) {
console.log(message);
}, function(error) {
console.log(error);
}).then(function() {
console.log('완료!');
});
여기까지는 흔한 제이쿼리 프로미스 방식이고 ES2015의 프로미스와도 상당히 유사합니다. 제이쿼리의 장점은 추가 메소드를 제공하는 겁니다.
$.when은 여러 개의 비동기 프로미스 함수를 동시에 처리할 수 있게 해줍니다.
$.when(longAndComplicatedFunction(), longerAndMoreComplicatedFunction()).done(function(result1, result2) {
console.log(result1, result2);
});