머리말
Promise와 처음으로 연락을 취한 것은 Microsoft가 2012 년에 Windows 8 운영 체제를 출시하고 HTML5를 사용하여 호기심 많은 태도로 메트로 응용 프로그램을 작성했을 때였습니다. 그 당시 HTML5와 함께 제공된 WinJS 라이브러리의 비동기 인터페이스는 모두 약속 형태였으며, 그 당시 JavaScript를 방금 졸업 한 나를위한 하늘의 책이었습니다. 당시 내가 생각했던 것은 Microsoft가 다시 땜질을하고 있다는 것이 었습니다.
예기치 않게 2015 년까지 약속은 실제로 ES6 표준에 기록되었습니다. 또한 설문 조사에 따르면 JS 프로그래머는이 항목을 상당히 높게 사용합니다.
아이러니하게도, 2012 년 초에 메트로 애플리케이션 개발 인터페이스에서 널리 사용 된 Microsoft로서, 자체 브라우저 IE는 여전히 2015 년에 사망 할 때까지 약속을지지하지 않았습니다. Microsoft에는이 기술이 없지만 실제로는 치료를 포기한 것으로 보입니다. . .
지금 되돌아 보면, 그 당시 약속을 보는 데있어 가장 번거로운 것은 초보자가 믿어지지 않는 것처럼 보이며 JS 프로그래머들에 의해 가장 널리 칭찬 된 기능이라는 것입니다.
그런 다음 기능 호출 체인은 본질적으로 여러 비동기 프로세스를 순서대로 호출하는 것입니다. 이 기사는이 시점부터 시작하여 연구를 연구하고 약속의 특징을 배웁니다.
약속 해결
다음 시나리오를 고려하십시오. 기능이 2 초 만에 지연되고 로그 라인을 인쇄 한 다음 3 초 만에 지연 된 다음 4 초를 지연시키고 로그 라인을 인쇄하십시오. 이것은 다른 프로그래밍 언어에서 매우 간단하지만 JS에 들어가기가 더 어렵고 코드는 다음과 같이 작성 될 것입니다.
var myfunc = function () {settimeout (function () {console.log ( "log1"); settimeout (function () {console.log ( "log2")); settimeout (function () {console.log ( "log3");}, 4000);}, 3000);};}중첩 된 다층 콜백 구조로 인해 여기에 전형적인 피라미드 구조가 형성됩니다. 비즈니스 논리가 더 복잡하다면 끔찍한 콜백 지옥이 될 것입니다.
더 나은 인식이 있고 간단한 기능을 추출하는 방법을 알고 있다면 코드는 다음과 같습니다.
var func1 = function () {settimeout (func2, 2000);}; var func2 = function () {console.log ( "log1"); settimeout (func3, 3000);}; var func3 = function () {console.log ( "log2"); settimeout (func4, 4000);}; var func4 = function () {console.log ( "log3");};이것은 조금 더 좋아 보이지만 항상 조금 이상합니다. . . 사실, JS 레벨은 제한되어 있으므로 왜 글을 잘 쓸 수 없는지 말할 수 없습니다. 이것이 왜 좋지 않은지 알고 약속을 발명했다면 알려주십시오.
이제 요점으로 돌아가서 약속에 대해 이야기합시다.
약속에 대한 설명
MDN의 약속에 대한 설명을 여기에서 인용 할 수 있습니다.
약속 객체는 연기 계산 및 비동기 계산에 사용됩니다. 약속 객체는 완료되지 않았지만 향후 완료 될 것으로 예상되는 작업을 나타냅니다.
Promise Object는 반환 값의 대리인이며, 약속 객체가 생성 될 때 알 수 없습니다. 비동기 작업의 성공 또는 고장을위한 취급 방법을 지정할 수 있습니다. 이를 통해 비동기 메소드는 동기 메소드와 같은 값을 반환 할 수 있습니다.
약속 대상에는 다음과 같은 상태가 있습니다.
• 보류 : 초기 상태, 가득 차지 또는 거부.
• 이행 : 성공적인 운영.
• 거부 : 작동 실패.
보류 상태가있는 약속 대상은 성공 값 또는 실패 메시지가있는 거부 상태로 이행 된 상태로 변환 될 수 있습니다. 상태가 전환되면 약속에 대한 방법 (기능 핸들)이 호출됩니다. (방법을 바인딩 할 때, 약속 객체가 이미 충족되거나 거부 된 상태에있는 경우, 해당 방법이 즉시 호출되므로 비동기 작동 완료와 바인딩 방법 사이에는 레이스 조건이 없습니다.)
더 많은 설명과 약속의 예는 MDN의 약속 항목 또는 MSDN의 약속 항목을 참조하십시오.
약속으로 우리의 문제를 해결하십시오
위의 약속에 대한 이해를 바탕으로, 우리는이를 사용하여 중첩 된 멀티 레이어 콜백의 코드가 어리 석고 유지하기가 어렵다는 문제를 해결할 수 있음을 알고 있습니다. 위에서 주어진 두 링크는 이미 약속의 구문 및 매개 변수에 대해 매우 명확합니다. 여기에서 반복하지 않고 코드를 업로드하겠습니다.
먼저 지연과 콜백을 한 번만 실행하는 비교적 간단한 케이스를 시도해 봅시다.
new Promise (function (res, Rej) {console.log (date.now () + "start settimeout"); settimeout (res, 2000);}). 그런 다음 (function () {console.log (date.now () + "timeout call back");});MSDN의 예와는 차이가 없으며 실행 결과는 다음과 같습니다.
$ node promistest.js1450194136374 Settimeout1450194138391 시간 초과 호출을 시작하십시오
그래서 우리가 또 다른 지연을하고 싶다면, 나는 이것을 쓸 수 있습니다.
New Promise (함수 (res, rej) {console.log (date.now () + "start settimeout 1"); settimeout (res, 2000);}) 3000); |올바르게 작동하는 것 같습니다.
$ node promistest.js1450194338710 Settimeout 시작 11450194340720 타임 아웃 1 호출 1450194340720 Settimeout 21450194343722 시간 초과 2 다시 전화
그러나 코드는 어리 석고 귀엽습니다. 다시 피라미드를 모호하게 구축하고 있습니다. 이것은 약속을 도입하려는 목적에 반대합니다.
그래서 문제는 무엇입니까? 올바른 자세는 무엇입니까?
답은 당시 함수의 반환 값에 숨겨져 있으며 당시 함수는 완성 된 (또는 oncompleted) 콜백 함수입니다.
우선, 당시 함수는 새로운 약속 변수를 반환하고 다음과 같이이 새로운 약속 변수의 기능을 다시 호출 할 수 있습니다.
새로운 약속 (...). 그런 다음 (...).
당시 기능에 의해 어떤 종류의 약속이 반환되는지는 성취 된 콜백의 반환 값에 따라 다릅니다.
실제로, 완전한 채워진 것은 정상 변수 또는 다른 약속 변수를 반환 할 수 있습니다.
onfuled가 정상 값을 반환하면 함수가 기본 약속 변수를 반환합니다. 당시 약속의 기능을 실행하면 약속을 즉시 만족시키고 성취 된 기능이 실행되며, 성취 된 입력 매개 변수는 이전에 완료 된 수익의 반환 값입니다.
onfulfilled가 약속 변수를 반환하면 해당 약속 변수가 당시 함수의 반환 값으로 사용됩니다.
MDN 및 MSDN의 문서에는 당시 기능 및 성취 된 기능에 대한이 일련의 설정에 대한 명확한 긍정적 인 설명이 없습니다. 공식 ES6 문서 ECMAScript 2015 (6th Edition, ECMA-262). . . 나는 내 수준을 정말로 이해할 수 없다. 전문가가 공식 문서의 두 리턴 값에 대한 설명을 설명 할 수 있다면 조언을 구할 메시지를 남겨주세요! ! !
위의 것은 나의 무료 놀이이며 언어 조직은 설명하기가 약간 어렵습니다. 코드를 읽은 후 이해할 것입니다.
첫째, 정상 변수를 반환하는 경우 :
New Promise (함수 (res, rej) {console.log (date.now () + "start settimeout 1"); settimeout (res, 2000);}). 그런 다음 (function () {console.log (date.now () + "timeout 1 전화"); 그런 다음 (1024;}). });위의 코드 실행 결과는 다음과 같습니다.
$ node promistest.js14502771222125 Settimeout 시작 11450277124129 시간 초과 1 호출 1450277124129 마지막 onfuiled return 1024
조금 흥미 롭지 만 핵심은 아닙니다. 핵심은 성취 된 함수가 약속 변수를 반환하여 여러 비동기 프로세스를 연속적으로 호출하는 것이 편리하다는 것입니다. 예를 들어, 우리는 두 번의 지연 작업을 연속적으로 수행 할 수 있습니다.
New Promise (함수 (res, rej) {console.log (date.now () + "start settimeout 1"); settimeout (res, 2000);}) 3000);});}). 그런 다음 (function () {console.log (date.now () + "timeout 2 Call Back");});실행 결과는 다음과 같습니다.
$ Node Promistest.js1450277510275 Settimeout 시작 11450277512276 시간 초과 1 호출 1450277512276 Settimeout 21450277515327 Timeout 2 다시 전화
이것이 좋지 않다고 생각한다면 몇 번 더 해보는 것은 문제가되지 않습니다.
New Promise (함수 (res, rej) {console.log (date.now () + "start settimeout 1"); settimeout (res, 2000);}) 3000);}). 타임 아웃 3 Call Back "); 새로운 약속을 반환합니다 (function (res, Rej) {console.log (date.now () +"start settimeout 4 "); settimeout (res, 5000);});});}).$ node promistest.js1450277902714 시작 설정 시작 시간 초 Settimeout 41450277916744 타임 아웃 4 전화를 끊습니다
다수의 지연 콜백 함수는 순서대로 배열되어 있으며, 인기있는 피라미드와 같은 구조는 없음을 알 수있다. 코드는 비동기 프로세스를 호출하지만 동기식 프로세스로 구성된 것처럼 보입니다. 이것이 약속이 우리에게 가져 오는 혜택입니다.
동점 코드를 별도의 기능으로 증류하는 좋은 습관이 있다면 더욱 아름답습니다.
function timeout1 () {return new Promise (function (res, Rej) {console.log (date.now () + "start timeout1"); settimeout (res, 2000);});} 함수 timeout2 () {return new Promise (res, rep) {console.log (date.now ()}); reture (settimeout (res, 3000)); timeout3 () {return new Promise (function (res, rej) {console.log (date.now () + "start timeout2"); settimeout (res, 3000);});} 함수 timeout3 () {return new Promise (res, reb) {console.log (date.now () + "settimeout (res, 4000);}; timeout4 () {return new Promise (function (res, Rej) {console.log (date.now () + "start timeout4"); settimeout (res, 5000);});} timeout1 () .then (timeout3) .then (timeout4) .then (function () + "); });$ Node Promistest.js1450278983342 시작 시간 초과 시작 11450278985343 시작 시간 초과 시작 2145027898351 시작 시간 초과 31450278992356 시작 시간 초과 시작 4145027897370 Timout4 Callback
다음으로, 우리는 성취 된 기능의 들어오는 매개 변수를 전달하는 문제를 계속 연구 할 수 있습니다.
우리는 이전에 완성 된 함수가 정상 값을 반환하는 경우이 값은 onfulfilled 함수의 입력 매개 변수라는 것을 이미 알고 있습니다. 그렇다면 이전에 성취 된 완료가 약속 변수를 반환하는 경우, 성소 된 입력 매개 변수는 어디에서 왔습니까?
답은이 성취 된 함수의 입력 매개 변수가 이전 약속에서 결의 기능이 호출 될 때 전달 된 값이라는 것입니다.
나는 한동안 점프를 받아 들일 수 없었다. 잘하자.
우선, 기능 약속은 무엇입니까? MDN 위의 Zou Zou의 진술 사용
성공 가치 값으로 약속 객체를 해결하십시오. 값이 연속적이면 (당시 방법으로, 당시 방법으로), 반환 된 약속 객체는 값을 "따라"합니다.
요컨대, 이것은 비동기 호출이 성공할 때 콜백입니다.
일반적인 비동기 인터페이스에서 콜백의 모습을 살펴 보겠습니다. nodejs에서 fs.readfile (파일 [, 옵션], 콜백)을 선택하십시오. 일반적인 호출 예제는 다음과 같습니다
fs.readfile ( '/etc/passwd', function (err, data) {if (err) trash err; console.log (data);});Fs.ReadFile 함수의 경우 성공 여부에 관계없이 콜백 함수 콜백을 호출 하므로이 콜백은 두 매개 변수, 즉 실패 오류에 대한 예외 설명과 성공에 대한 리턴 결과 데이터를 수용합니다.
따라서이 파일을 읽는이 예제를 재구성하기 위해 약속을 사용한다면 어떻게 작성해야합니까?
먼저 fs.readfile 함수를 캡슐화하십시오.
함수 readfile (filename) {return new Promise (function (resolve (resolve), 거부) {fs.ReadFile (filename, function (err, data) {if (err) {reject (err);} else {resolve (data);}});});});});두 번째는 전화입니다.
readfile ( 'thefile.txt'). 그런 다음 (함수 (data) {console.log (data);}, function (err) {trash err;});파일의 내용이 일반적으로 다른 언어로 파일을 읽는 동기식 통화 인터페이스에 위치하는 위치를 상상해보십시오. 함수 반환 값이 정확합니까? 대답은이 결의의 진입 인삼은 무엇입니까? 비동기 호출이 성공하면 반환 값입니다.
이 개념을 사용하면 "성취 된 함수의 입력 매개 변수가 이전 약속에서 해상도 기능을 호출 할 때 전달되는 값"을 이해하는 것은 어렵지 않습니다. 성취 된 작업은 이전의 비동기 호출이 성공한 후 결과를 처리하는 것입니다.
아아는 마침내 곧게 나왔습니다. . .
요약
코드를 사용 하여이 기사에서 설명한 핵심 사항을 요약하십시오.
함수 callp1 () {console.log (date.now () + "start callp1"); 새로운 약속을 반환합니다 (function (res, Rej) {settimeout (res, 2000);});} 함수 callp2 () {console.log (date.now () + "start callp2"); return new Promise (function (res, Rej) {settimeout (function () {res ({arg1 : 4, arg2 : "arg2 value"});}, 3000);} 함수 callp3 (arg) {console.log (date.now ()) + "arg =" + arg); return new Promise (function (res) {settimeout (function () {res ( "callp3");}, arg * 1000);};} callp1 (). value = " + json.stringify (ret)); return callp3 (ret.arg1);}). 그런 다음 (function (ret) {console.log (date.now () +"callp3 ret value = " + ret);}); $ Node Promistest.js1450191479575 START CALLP11450191481597 CALLP1 return1450191481599 시작 Callp21450191484605 reture value = {arg1 ": 4,"arg2 value "} 145019191484605 with with with with with rate 41450191488610 Callp3 Ret value = Callp3로 반환합니다다층 비동기 통화를 해결하기 위해 약속을 사용하는 위의 간단한 학습 경험은 내가 공유하는 모든 콘텐츠입니다. 나는 당신이 당신에게 참조를 줄 수 있기를 바랍니다. 그리고 당신이 wulin.com을 더 지원할 수 있기를 바랍니다.