현재 많은 수의 비동기 작업이 수요에 관여하고 있으며 실제 페이지는 단일 페이지 응용 프로그램에 점점 더 기울어지고 있습니다. 앞으로 백본, 각도, 녹아웃 및 기타 프레임 워크를 사용할 수 있지만 비동기 프로그래밍 문제는 첫 번째 문제입니다. 노드의 부상으로 비동기 프로그래밍은 매우 인기있는 주제가되었습니다. 학습과 실습 기간이 지나면 비동기 프로그래밍에 대한 일부 세부 사항이 요약되어 있습니다.
1. 비동기 프로그래밍의 분류
비동기 문제를 해결하는 방법에는 일반적으로 직접 콜백, 펍/하위 모드 (이벤트 모드), 비동기 라이브러리 제어 라이브러리 (예 : Async, 언제), 약속, 생성기 등이 포함됩니다.
1.1 콜백 함수
콜백 기능은 일반적으로 비동기 솔루션을 해결하는 데 사용되며, 종종 노출 및 사용되며 이해하기 쉽고 라이브러리 나 기능에서 구현하기 쉽습니다. 이것은 또한 사람들이 비동기 프로그래밍을 사용할 때 종종 사용하는 방법입니다.
그러나 콜백 함수 메소드에는 다음과 같은 문제가 있습니다.
1. 중첩 된 악의 피라미드가 형성 될 수 있으며, 코드는 읽기 쉽지 않습니다.
2. 하나의 콜백 함수 만 해당 할 수 있으며, 이는 많은 시나리오에서 한계가됩니다.
1.2 펍/하위 모드 (이벤트)
이 패턴을 이벤트 모드라고도하며 콜백 기능의 이벤트화이며 jQuery와 같은 클래스 라이브러리에서 매우 일반적입니다.
이벤트 게시 가입자 모드 자체는 동기 및 비동기 호출 문제가 없지만 노드에서는 이벤트 루프와 비동기로 방출 호출이 발생합니다. 이 모드는 종종 비즈니스 로직을 분리하는 데 사용됩니다. 이벤트 게시자는 등록 된 콜백 함수에주의를 기울일 필요가 없으며 콜백 함수 수에주의를 기울일 필요가 없습니다. 메시지를 통해 데이터를 유연하게 전송할 수 있습니다.
이 패턴의 이점은 다음과 같습니다. 1. 이해하기 쉽습니다. 2. 더 이상 하나의 콜백 함수로 제한되지 않습니다.
나쁜 일에 관해서는 : 1. 클래스 라이브러리를 사용해야합니다. 2. 이벤트 및 콜백 기능의 순서는 매우 중요합니다.
코드 사본은 다음과 같습니다.
var img = document.querySelect (#ID);
img.addeventListener ( 'load', function () {
// 사진이로드되었습니다
......
});
img.addeventListener ( 'error', function () {
// 뭔가 잘못되었습니다
......
});
위 코드에는 두 가지 문제가 있습니다.
에이. IMG가 실제로로드되었으며 현재로드 콜백 기능이 바운드되었습니다. 결과적으로 콜백은 실행되지 않지만 여전히 해당 콜백 기능을 실행하기를 희망합니다.
코드 사본은 다음과 같습니다.
var img = document.querySelect (#ID);
함수 load () {
...
}
if (img.complete) {
짐();
} 또 다른 {
img.addeventListener ( 'load', load);
}
img.addeventListener ( 'error', function () {
// 뭔가 잘못되었습니다
......
});
비. 예외를 잘 처리 할 수 없습니다
결론 : 이벤트 메커니즘은 동일한 객체에서 반복적 인 이벤트를 다루는 데 가장 적합하며 콜백 함수가 바인딩되기 전에 이벤트를 고려할 필요가 없습니다.
1.3 비동기 제어 라이브러리
현재 비동기 라이브러리에는 주로 q, when.js, win.js, rsvp.js 등이 포함됩니다.
이러한 라이브러리의 특징은 코드가 선형이며 자연 습관에 따라 위에서 아래로 쓸 수 있다는 것입니다.
나쁜 것은 또한 스타일에서 다르며, 이는 학습 비용을 읽고 늘리는 데 불편합니다.
1.4 약속
약속은 약속으로 중국어로 번역됩니다. 개인적으로, 비동기 적으로 완료 한 후에는 외부 결과 (성공 또는 실패)를 제공하고 결과가 더 이상 변경되지 않을 것이라고 약속합니다. 다시 말해, 약속은 작업의 최종 반환 결과 값을 반영합니다 (약속은 작업의 단일 완료에서 반환 된 최종 값을 나타냅니다). 현재 Promise가 ES6 사양에 도입되었으며 Chrome 및 Firefox와 같은 고급 브라우저는 내부적 으로이 기본 방법을 구현했으며 이는 사용하기에 매우 편리합니다.
다음은 다음 측면에서 약속의 특성입니다.
1.4.1 상태
여기에는 계류, 이행 및 거부 된 세 가지 상태가 포함되어 있습니다. 세 국가는 두 번의 전환을 거칠 수 있으며 (보류 중 ---> 이행, 보류 중-> 거부), 국가의 전환은 한 번만 발생할 수 있습니다.
1.4.2 방법
당시 방법은 비동기 이벤트가 완료된 후 콜백 함수를 지정하는 데 사용됩니다.
이 방법은 영혼의 약속의 방법이라고 할 수 있으며,이 방법은 마법으로 가득 차 있습니다. 다음과 같이 몇 가지 특정 증상이 있습니다.
a) 그러면 방법은 약속을 반환합니다. 이를 통해 여러 비동기 작업의 직렬 작업이 가능합니다.
위 그림에서 노란색 원 1과 관련하여 가치 처리는 약속의 더 복잡한 부분입니다. 가치 처리는 약속 물체와 비 프로모션 객체의 두 가지 상황으로 나뉩니다.
값이 약속 유형이 아닌 경우 값을 두 번째 약속의 해결의 매개 변수 값으로 사용하십시오. 약속 유형 인 경우 Promise2의 상태 및 매개 변수는 값에 의해 완전히 결정됩니다. Promsie2는 가치의 꼭두각시이며 Promise2는 다른 비동기를 연결하는 다리 일뿐입니다.
코드 사본은 다음과 같습니다.
promise.prototype.then = 함수 (onfulfilled, onrejected) {
새로운 약속을 반환합니다 (함수 (Resolve, Reject) {// 여기의 약속은 약속 2로 표시됩니다.
핸들({
성취 된 : 성취, 완료,
onerefered : onerefeded,
결의 : 해결,
거부 : 거부
})
});
}
기능 핸들 (연기) {
var handlefn;
if (state === 'fulfired') {
handlefn = 연기.
} else if (state === '거부') {
handlefn = 연기. 반사;
}
var ret = handlefn (값);
Deferred.resolve (ret); // 현재의 결의는 약속의 결의입니다.
}
함수 Resolve (val) {
if (val && typeof val.then === 'function') {
Val.Then (Resolve); // Val이 약속 대상이거나 클래스 약속 대상인 경우 Promise의 상태 2는 Val에 의해 완전히 결정됩니다.
반품;
}
if (콜백) {// 콜백은 지정된 콜백 함수입니다
콜백 (val);
}
}
b) 여러 다른 비동기 라이브러리 간의 변환이 구현됩니다.
비동기식으로 불리는 객체가 있는데,이 방법은 당시 메소드가있는 객체를 나타냅니다. 객체 객체에 당시 메소드가있는 한, 예를 들어 변환 할 수 있습니다.
코드 사본은 다음과 같습니다.
var deferred = $ ( 'aa.ajax'); // !! 연기
var p = promise.resolve (연기);
P. 그 (......)
1.4.3 Commonjs Promise/A 사양
현재 약속에 관한 사양에 대한 약속/A 및 약속/A+ 사양이 있으며, 이는 약속의 이행이 상당히 복잡하다는 것을 보여줍니다.
코드 사본은 다음과 같습니다.
그런 다음 (fulfedhandler, RejectedHandler, ProgressHandler)
1.4.4 노트
약속의 콜백 함수는 값을 공유합니다. 결과 처리에서 값은 해당 콜백 함수의 매개 변수로 전달됩니다. 값이 객체 인 경우 값을 쉽게 수정하지 않도록주의하십시오.
코드 사본은 다음과 같습니다.
var p = promise.resolve ({x : 1});
P. then (function (val) {
Console.log ( '첫 번째 콜백 :'+val.x ++);
});
P. then (function (val) {
Console.log ( '두 번째 콜백 :' + val.x)
})
// 첫 번째 콜백 : 1
// 두 번째 콜백 : 2
1.5 생성기
위의 모든 방법은 콜백 함수를 기반으로하여 비동기 작업을 완료하며 콜백 기능을 캡슐화하는 것 이상입니다. ES6은 발전기를 제안하여 비동기 작업을 해결하는 방법을 추가하고 콜백 함수를 기반으로 더 이상 완료되지 않습니다.
발전기의 가장 큰 특징은 기능을 일시 중지 및 다시 시작할 수 있다는 것입니다. 이는 비동기 작업을 해결하는 데 매우 도움이됩니다. 생성기의 일시 정지를 약속의 예외 처리와 결합하면 비동기 프로그래밍 문제를보다 우아하게 해결할 수 있습니다. 구체적인 구현 참조 : Kyle Simpson
2. 비동기 프로그래밍 문제
2.1 예외 처리
A) 비동기 이벤트에는 두 가지 링크가 포함됩니다. 비동기 요청 발행 및 처리 결과. 이 두 링크는 이벤트 루프를 통해 연결됩니다. 그런 다음 Catch에서 예외 캡처를 수행하려면 캡처해야합니다.
코드 사본은 다음과 같습니다.
노력하다 {
비동기 (콜백);
} catch (err) {
......
}
위의 코드는 콜백에서 예외를 포착 할 수 없으며 요청 프로세스에서만 예외 만 얻을 수 있습니다. 문제가 있습니다. 요청 발행과 요청 처리가 두 사람이 완료하면 예외를 처리 할 때 문제가 있습니까?
b) Promise는 예외 배송을 구현하여 실제 프로젝트에서 코드가 차단되지 않도록 몇 가지 이점을 제공합니다. 그러나 비동기 이벤트가 많으면 어떤 비동기 이벤트가 예외를 생성하는지 쉽게 찾을 수 없습니다.
코드 사본은 다음과 같습니다.
// 장면 설명 : 경쟁 정보를 포함하여 CRM의 가격 경보 정보 표시. 그러나 경쟁 정보를 얻는 데 시간이 오래 걸립니다. 느린 쿼리를 피하기 위해 백엔드는 레코드를 두 조각으로 나누어 별도로 얻습니다.
// 1 단계 : 경쟁 정보 외에 가격 경보 정보 얻기
함수 getPriceAlarMData () {
새로운 약속을 반환합니다 (기능 (Resolve) {
y.io (url, {
방법 : 'get',
데이터 : 매개 변수,
on : function () {
성공 : 함수 (id, data) {
해결 (알람 다타);
}
}
});
});
}
// 경보 정보를 얻은 후 경쟁 정보를 얻으십시오.
getPriceAlarMData (). 그런 다음 (함수 (데이터) {
// 경쟁 정보 외에도 데이터 렌더링
렌더 (데이터);
새로운 약속을 반환합니다 (기능 (Resolve) {
y.io (url, {
방법 : 'get',
데이터 : {alarmlist : data},
on : function () {
성공 : 함수 (id, compdata) {
Resolve (compdata);
}
}
});
});
}) // 모든 데이터를 얻은 후 경쟁 정보 렌더링
. 그런 다음 (함수 (데이터) {
// 입찰 정보를 렌더링합니다
렌더 (데이터)
}, function (err) {
// 예외 처리
Console.log (err);
});
위의 코드는 다음으로 변환 할 수 있습니다.
코드 사본은 다음과 같습니다.
노력하다{
// 경쟁 이외의 경보 정보를 얻습니다
var alarmdata = AlarmDataExceptCompare ();
렌더 (알람 다타);
// 경보 정보를 기반으로 한 경쟁 정보 문의
var 비교 = getCompareInfo (알람 다타);
렌더 (비교);
} catch (err) {
Console.log (err.message);
}
위의 예에서는 예외가 끝에서 처리되므로 특정 링크에서 예외가 발생하면 정확히 어떤 이벤트가 생성되는지 알 수 없습니다.
2.2 jQuery.deferred 문제
비동기 작업은 jQuery에서도 구현되지만 구현시 약속/A+ 사양을 준수하지 않으며 주로 다음 측면에 반영됩니다.
에이. 매개 변수 수 : 표준 약속은 하나의 매개 변수 만 수용 할 수 있지만 jQuery
코드 사본은 다음과 같습니다.
함수 asyncinjQuery () {
var d = new $ .deferred ();
settimeout (function () {
D.Resolve (1, 2);
}, 100);
return d.promise ()
}
asyncinjquery ().
Console.log ( '출력 :', val1, val2);
});
// 출력 : 1 2
비. 결과 처리의 예외 처리
코드 사본은 다음과 같습니다.
함수 asyncinPromise () {
새로운 약속을 반환합니다 (기능 (Resolve) {
settimeout (function () {
var jsonst = '{ "name": "mt}';
결의 (JSONST);
}, 100);
});
}
asyncinPromise (). 그런 다음 (함수 (val) {
var d = json.parse (val);
Console.log (D.Name);
}). 그런 다음 (null, function (err) {
console.log ( 'show error :' + err.message);
});
// 오류 표시 : 예상치 못한 입력 끝
함수 asyncinjQuery () {
var d = new $ .deferred ();
settimeout (function () {
var jsonst = '{ "name": "mt}';
D.Resolve (JSONST);
}, 100);
return d.promise ()
}
asyncinjquery (). 그런 다음 (function (val) {
var d = json.parse (val);
Console.log (D.Name);
}). 그런 다음 (함수 (v) {
Console.log ( 'success :', v.name);
}, function (err) {
console.log ( 'show error :' + err.message);
});
// 끊임없는 syntaxError : 예기치 않은 입력 끝
콜백 함수의 실행 중에 예외를 캡처 할 수 있지만 jQuery.Deferred는 할 수없는 콜백 함수의 결과를 약속하는 것을 이로부터 볼 수 있습니다.