이 기사는 주로 약속의 사용을 대중화합니다.
오랫동안 JavaScript는 항상 콜백 형태로 비동기 적으로 처리되어 왔으며 프론트 엔드 개발 분야의 콜백 메커니즘은 사람들의 마음에 거의 뿌리를두고 있습니다. 브라우저 제조업체, SDK 개발자 또는 다양한 라이브러리의 저자이든 API를 설계 할 때는 기본적으로 콜백 루틴을 따릅니다.
최근 몇 년 동안 JavaScript 개발 모델의 점진적인 성숙함으로 Promise Specification의 제안을 포함하여 CommonJS 사양이 탄생했습니다. Promise는 JS 비동기 프로그래밍의 글쓰기를 완전히 바꾸어 비동기 프로그래밍을 매우 쉽게 이해할 수있었습니다.
콜백 모델에서는 비동기 큐를 실행해야한다고 가정하고 코드는 다음과 같습니다.
loadImg ( 'a.jpg', function () {loadImg ( 'b.jpg', function () {loadimg ( 'c.jpg', function () {console.log ( 'All Dog!');});});이것이 우리가 종종 피라미드를 부르는 것입니다. 많은 비동기적인 작업이 있으면 많은 수의 콜백을 유지하는 것이 재앙이 될 것입니다. 요즘 Node.js는 매우 인기가 있습니다. 많은 팀이 "패션"과 어울릴 무언가를 만들기 위해 그것을 사용하고 싶어하는 것 같습니다. 작업 및 유지 보수 급우와 채팅을 한 후에는 Node.js를 사용하여 무언가를 할 계획 이었지만 JS의 콜백 레이어를 생각하면 낙담합니다.
좋아요, 말도 안되는 일이 끝났습니다. 주제에 도달합시다.
약속 사양이 오랫동안 나왔고 약속이 ES6에 포함되어 있었고, Chrome 및 Firefox 브라우저의 더 높은 버전은 기본적으로 약속을 구현했지만 오늘날 인기있는 Promise Class 라이브러리보다 API가 적습니다.
소위 약속은 문자 그대로 "약속"으로 이해 될 수 있으며, 이는 B, B가 A에 "약속"을 반환 한 다음 A가 계획을 작성할 때이를 작성할 수 있음을 의미합니다. B가 나에게 결과를 반환 할 때 A는 계획 S1을 실행합니다. 반대로, B가 원하는 이유에 대해 원하는 결과를 제공하지 않으면 A는 비상 계획 S2를 실행하여 모든 잠재적 위험이 A의 제어 가능한 범위 내에 있도록합니다.
위의 문장은 다음과 유사한 코드로 변환됩니다.
var resb = b (); var runa = function () {resb.then (execs1, execs2);}; runa ();위의 코드 줄을 보면 특별한 것이없는 것 같습니다. 그러나 현실은 이것보다 훨씬 더 복잡 할 수 있습니다. 한 가지를 달성하기 위해 A는 한 명 이상의 사람 B의 응답에 의존 할 수 있습니다. 여러 사람에게 동시에 요청한 다음 모든 답변을받은 후 다음 계획을 구현해야 할 수도 있습니다. 코드로의 최종 변환은 다음과 같습니다.
var resb = b (); var resc = c (); ... var runa = function () {reqb .then (resc, execs2) .then (resd, execs3) .then (rese, execs4) .... then (execs1);}; rena ();여기서, 각각의 문의 된 응답이 기대에 부응하지 않는 응답을 할 때 다른 처리 메커니즘이 사용됩니다. 실제로, 약속 사양은 이것을 요구하지 않으며, 아무것도하지 않을 수도 있고 (즉, 두 번째 매개 변수에 전달되지 않음) 균일하게 처리 할 수 있습니다.
좋아, 약속/A+ 사양을 알아 보겠습니다.
then 방법을 구현해야합니다 (약속의 핵심이라고 말할 수 있습니다). 그런 다음 약속을 반환해야합니다. 그런 다음 동일한 약속의 여러 번 호출 될 수 있으며 콜백의 실행 순서는 정의 된 순서와 일치합니다.보시다시피, 약속 사양에는 많은 내용이 없으므로 다음 약속을 직접 구현할 수 있습니다.
다음은 많은 약속 도서관을 언급 한 약속의 간단한 구현입니다. 코드에서 Promisea로 이동하십시오.
아이디어에 대한 간단한 분석 :
생성자 약속은 함수 resolver 수락하며, 이는 비동기 작업을 통과하는 것으로 이해 될 수 있습니다. Resolver는 두 개의 매개 변수를 수락합니다. 하나는 성공할 때 콜백이고 다른 하나는 고장시 콜백입니다. 이 두 매개 변수는 그때 통과 된 매개 변수와 같습니다.
두 번째는 그때의 구현입니다. 약속은 약속을 반환해야한다는 약속이 필요하기 때문에, 그 당시에 전화 할 때 새로운 약속이 생성 될 것이며, 현재 약속의 _next 에 매달려있을 것입니다. 동일한 약속의 여러 호출은 이전에 생성 된 _next 만 반환합니다.
당시 메소드에 의해 허용되는 두 매개 변수는 선택 사항이며 유형에 제한이 없으므로 함수, 특정 값 또는 다른 약속 일 수 있습니다. 다음은 다음과 같은 특정 구현입니다.
promise.prototype.then = 함수 (Resolve, Reject) {var next = this._next || (this._next = promise ()); var status = this.status; var x; if ( 'pending'=== status) {isfn (resolve) && this._resolves.push (resolve); isfn (거부) && this._rejects.push (거부); 다음으로 돌아갑니다. } if ( 'resolved'=== status) {if (! isfn (resolve)) {next.resolve (resolve); } else {try {x = resolve (this.value); Resolvex (다음, x); } catch (e) {this.reject (e); }} 다음에 반환; } if ( '거부'=== 상태) {if (! isfn (Reject)) {next.reject (거부); } else {try {x = Reject (this.reason); Resolvex (다음, x); } catch (e) {this.reject (e); }} 다음에 반환; }};여기에서 다른 약속 클래스 라이브러리의 구현을 단순화했으며 구현은 이보다 훨씬 더 복잡하며 더 많은 기능이 있습니다. 예를 들어, 세 번째 매개 변수 - Notify는 현재 약속의 현재 진행 상황을 나타내며, 이는 디자인 파일을 업로드 할 때 매우 유용합니다. 그 당시의 다양한 매개 변수의 처리가 가장 복잡한 부분입니다. 관심있는 학생들은 다른 유형의 약속 도서관의 구현을 참조 할 수 있습니다.
그때에 기초하여, 약속 상태가 보류 중이거나 해결되거나 거부되도록 약속 상태의 전환을 완료하고 해당 콜백 큐 resolve() 실행하기 위해서는 최소한 reject() 가지 방법이 필요합니다.
이 시점에서 간단한 약속이 설계되었습니다. 다음은 다음 두 가지 약속 된 기능의 간단한 구현입니다.
함수 sleep (ms) {return function (v) {var p = promise (); settimeout (function () {p.resolve (v);}, ms); 반환 p; };}; 함수 getImg (url) {var p = promise (); var img = new Image (); img.onload = function () {p.resolve (this); }; img.onerror = function (err) {p.reject (err); }; img.url = url; 반환 p;}; 약속 생성자는 매개 변수로 비동기 작업을 수용하므로 getImg 도 다음과 같이 호출 할 수 있습니다.
function getImg (url) {return promise (function (resolve (resolve), Reject) {var img = new image (); img.onload = function () {resolve (this);}; img.onerror = function (err);}; img.url = url;};};다음으로 (기적을 목격하는 순간), 이것을 구현하기위한 BT 요구 사항이 있다고 가정하십시오. JSON 구성을 비동기로 비동기로 가져오고, JSON 데이터를 구문 분석하고 내부에 그림을 가져온 다음 사진을 순서대로로드 한 다음 그림이로드되지 않으면 로딩 효과를 제공하십시오.
함수 addimg (img) {$ ( '#list'). 찾기 ( '> li : last-Child'). html ( ''). append (img);}; function prepend () {$ ( '<li>') .html ( '로딩 ...') getData ( 'map.json') .then (function (data) {$ ( 'h4'). html (data.name); return data.rist.reduce (function (promise, item) {return promise (prepend) .then (sleep (1000)). then (return () {leccent getimg (item.url);}) promise.resolve ()); then (sleep (300)).여기에 수면이 추가되어 효과를보기 위해 클릭하여 클릭하여 데모를 볼 수 있습니다! 물론 Node.js 예제는 여기에서 볼 수 있습니다.
여기서, 정적 Promise.resolve(v) 의 방법은 긍정적 인 결과로 v와의 약속을 단순히 반환합니다. v는 전달할 수 없거나 then 방법 (즉, 당시 가능한)을 포함하는 객체 또는 함수 일 수 있습니다.
유사한 정적 방법에는 Promise.cast(promise) 포함되며, 이는 긍정적 인 결과로 약속을 가진 약속을 생성합니다.
Promise.reject(reason) 부정적인 결과로 이유가있는 약속을 생성합니다.
우리의 실제 사용 시나리오는 매우 복잡 할 수 있으며 종종 여러 비동기 작업이 산재, 평행 또는 연속적으로 실행되도록해야합니다. 현재 약속을 이행하고 약속을 수락하고 계속하기 전에 약속을 수락하고 예를 들어 Promise.all() Promise.any() 와 같은 약속이 완료 상태에있을 때 다음 작업이 시작됩니다.
이 기사를 html5rocks JavaScript 약속에서 참조 할 수 있습니다. 현재 Chrome 및 Firefox와 같은 고급 브라우저에는 Promise.all() 과 같은 더 많은 작동 인터페이스를 제공하는 약속 배열을 지원 한 다음 모든 약속이 완료되면 실행됩니다. 보다 친절하고 강력한 예외 캡처도 있습니다.이 캡처는 일일 비동기 프로그래밍을 처리하기에 충분해야합니다.
오늘날 가장 인기있는 JS 라이브러리는 Dojo, JQuery, Zepto, When.js, Q 등과 같은 다양한 학위에 대한 약속을 시행했지만 대부분의 노출 된 객체는 Deferred . jQuery (Zepto 유사)를 예로 들어, 위의 getImg() 구현하십시오.
함수 getImg (url) {var def = $ .deferred (); var img = new Image (); img.onload = function () {def.resolve (this); }; img.onerror = function (err) {def.reject (err); }; img.src = url; return def.promise ();}; 물론, jQuery에서는 많은 운영이 연기되거나 ajax 와 같은 약속을 animate 하거나 약속합니다.
// ajax $ .ajax (exacity ': 0}, 1000) .promise () .then (function () {console.log ('done ');}); // ajax $ .ajax (옵션); $. ajax (옵션) .Done (성공); // ajax $. $ .ajax (Options2)). (function () {console.log ( 'All Doge.');}, function () {console.error ( '뭔가 잘못된 것입니다.'); jQuery는 또한 done() 및 fail() 메소드를 구현하며, 실제로는 당시 방법의 바로 가기입니다.
약속의 대기열을 처리하려면 jQuery는 $.when() 방법을 구현하고 사용량은 Promise.all() 과 유사합니다.
다른 클래스 라이브러리의 경우, JS가 약속을 완전히 구현하고, 브라우저 및 Node.js를 지원하며, 더 풍부한 API를 제공하는 것이 좋습니다. 이는 좋은 선택입니다. 공간 제한으로 인해 더 이상 확장되지 않습니다.
우리는 약속의 구현이 아무리 복잡하더라도 사용법은 매우 간단하며 조직 코드는 매우 명확하다는 것을 알 수 있습니다. 이제부터 콜백으로 고문을받을 필요가 없습니다.
마지막으로, 약속은 너무 우아합니다! 그러나 약속은 콜백의 깊은 둥지 문제 만 해결합니다. JavaScript 비동기 프로그래밍을 실제로 단순화하는 생성기입니다. Node.js 측면에서 생성기를 고려하는 것이 좋습니다.
다음 기사, 연구 생성기.
github 원본 텍스트 : https://github.com/chemdemo/chemdemo.github.io/issues/6