예를 들어 페이지에서 Google Maps API를 호출할 때 Promise가 사용됩니다.
function success(position){ var cords = position.coords; console.log(coords.latitude + coords.longitude); } function error(err){ console.warn(err.code+err.message) } navigator.geolocation.getCurrentPosition(success, error);
■ 다중 비동기 메소드 처리 방법
순차적으로 실행해야 하는 비동기 메서드가 많으면 어떻게 되나요? async1(성공, 실패), async2(성공, 실패), ...asyncN(성공, 실패), 어떻게 처리하나요?
가장 간단한 것은 다음과 같이 작성할 수 있습니다.
async1(function(){ async2(function(){ ... asyncN(null, null); ... }, null) }, null)
위 코드는 상대적으로 유지 관리가 어렵습니다.
모든 비동기 메서드가 실행된 후에 알림이 표시되도록 할 수 있습니다.
var counter = N; function success(){ counter--; if(counter === 0){ alert('done'); } } async1(success); async2(success); ... asyncN(success);
■ 약속과 연기란 무엇인가
deferred는 비동기 작업의 결과를 나타내고 작업 결과와 상태를 표시하는 인터페이스를 제공하며 작업 결과를 얻을 수 있는 Promise 인스턴스를 제공합니다. Deferred는 작업 상태를 변경할 수 있습니다.
Promise는 관련 지연 항목과 상호 작용하기 위한 인터페이스를 제공합니다.
지연된 상태를 생성하는 것은 보류 상태와 동일합니다.
해결 메서드가 실행되면 해결된 상태와 동일합니다.
거부 메서드가 실행되면 거부된 상태와 동일합니다.
연기된 항목을 생성한 후 콜백 함수를 정의할 수 있으며, 콜백 함수는 해결 및 거부된 상태 프롬프트를 받은 후 실행을 시작합니다. 비동기 메서드는 콜백 함수가 어떻게 작동하는지 알 필요가 없으며 해결 또는 거부된 상태를 얻은 후 실행을 시작하도록 콜백 함수에 알리기만 하면 됩니다.
■ 기본 사용법
→ 연기 생성
var myFirstDeferred = $q.defer();
여기서 지연된 myFirstDeferred의 경우 상태는 보류 중입니다. 다음으로 비동기 메서드가 성공적으로 실행되면 상태가 해결되고 비동기 메서드가 실패하면 상태가 거부됩니다.
→ 이 지연된 문제를 해결하거나 거부합니다
비동기 메소드가 있다고 가정해보세요: async(success, failure)
async(function(value){ myFirstDeferred.resolve(value); }, function(errorReason){ myFirstDeferred.reject(errorReason); })
AngularJS에서 $q의 확인 및 거부는 컨텍스트에 의존하지 않으며 대략 다음과 같이 작성할 수 있습니다.
async(myFirstDeferred.resolve, myFirstDeferred.reject);
→ 연기된 약속 사용
var myFirstPromise = myFirstDeferred.promise; myFirstPromise .then(function(data){ }, function(error){ })
deferred는 여러 약속을 가질 수 있습니다.
var anotherDeferred = $q.defer(); anotherDeferred.promise .then(function(data){ },function(error){ }) //调用异步方法 async(anotherDeferred.resolve, anotherDeferred.reject); anotherDeferred.promise .then(function(data){ }, function(error){ })
위에서 비동기 메서드인 async가 성공적으로 실행되면 두 가지 성공 메서드가 모두 호출됩니다.
→ 일반적으로 비동기 메서드를 함수로 래핑합니다
function getData(){ var deferred = $q.defer(); async(deferred.resolve,deferred.reject); return deferred.promise; } //deferred的promise属性记录了达到resolved, reject状态所需要执行的success和error方法 var dataPromise = getData(); dataPromise .then(function(data){ console.log('success'); }, function(error){ console.log('error'); })
성공 콜백 함수에만 집중한다면 어떻게 작성하나요?
dataPromise .then(function(data){ console.log('success'); })
오류 콜백 기능에만 집중한다면 어떻게 작성하나요?
dataPromise .then(null, function(error){ console.log('error'); }) 或 dataPromise.catch(function(error){ console.log('error'); })
성공이나 실패에 관계없이 콜백이 동일한 결과를 반환하면 어떻게 되나요?
var finalCallback = function(){ console.log('不管回调成功或失败都返回这个结果'); }
dataPromise.then(finalCallback, finalCallback);
또는
dataPromise.finally(finalCallback);
■ 가치사슬
deferred.resolve를 사용하여 값을 반환하는 비동기 메서드가 있다고 가정합니다.
function async(value){ var deferred = $q.defer(); var result = value / 2; deferred.resolve(result); return deferred.promise; }
반환되는 것은 약속이므로 그때그때 계속할 수 있습니다.
var promise = async(8) .then(function(x){ return x+1; }) .then(function(x){ return x*2; }) promise.then(function(x){ console.log(x); })
위에서 Resolve의 값은 각 체인의 실제 매개변수가 됩니다.
■ Promise Chaining
function async1(value){ var deferred = $q.defer(); var result = value * 2; deferred.resolve(result); return deferred.promise; } function async2(value){ var deferred = $q.defer(); var result = value + 1; deferred.resolve(result); return deferred.promise; } var promise = async1(10) .then(function(x){ return async2(x); }) promise.then(function(x){ console.log(x); })
물론 더 읽기 쉽게 작성하는 방법은 다음과 같습니다.
function logValue(value){ console.log(value); } async1(10) .then(async2) .then(logValue);
async1 메소드의 반환 값은 then 메소드의 Success 메소드에서 실제 매개변수가 됩니다.
예외 포착의 관점에서 다음과 같이 작성할 수도 있습니다.
async1() .then(async2) .then(async3) .catch(handleReject) .finally(freeResources);
■ $q.reject(이유)
이 방법을 사용하면 지연된 항목이 오류 상태로 나타나게 하고 오류에 대한 이유를 제공할 수 있습니다.
var promise = async().then(function(value){ if(true){ return value; } else { return $q.reject('value is not satisfied'); } })
■ $q.when(값)
가치 있는 약속을 반환합니다.
function getDataFromBackend(query){ var data = searchInCache(query); if(data){ return $q.when(data); } else { reutrn makeAasyncBackendCall(query); } }
■ $q.all(promisesArr)
모든 약속이 실행될 때까지 기다립니다.
var allPromise = $q.all([ async1(), async2(), ... asyncN(); ]) allProise.then(function(values){ var value1 = values[0], value2 = values[1], ... valueN = values[N]; console.log('all done'); })
위 내용은 모두의 공부에 도움이 되기를 바랍니다.