JavaScript의 Promise에 대한 자세한 소개
1. 소개
JavaScript는 단일 스레드이므로 한 번에 하나의 작업만 실행할 수 있습니다. 작업 시간이 오래 걸리면 후속 작업을 기다려야 합니다. 그렇다면 이런 문제를 해결할 수 있는 방법은 없을까? (WebWorker는 제쳐두고), 이는 코드가 비동기적으로 실행되도록 하는 것입니다. 예를 들어, Ajax 비동기 요청을 수행할 때 지정된 콜백 함수의 실행을 결정하기 위해 ReadyState 값이 지속적으로 모니터링됩니다.
일반적으로 비동기 실행에는 콜백 함수, 이벤트 수신, 게시 및 구독의 세 가지 유형이 있습니다. 이벤트 수신과 게시 및 구독은 실제로 유사하지만 후자가 더 강력합니다.
콜백 함수와 마찬가지로 콜백 함수는 비동기 실행에 적용되는 가장 간단한 프로그래밍 아이디어입니다.
function async(item,callback){ console.log(item); setTimeout(function(){ callback(item+1); },1000); }
위의 예에서 async 함수가 실행되면 인쇄 작업이 완료되고 1초 후에 콜백 함수가 실행됩니다(그러나 반드시 1초일 필요는 없음, 자세한 내용은 "setTimeout things" 참조). 세부).
비동기식의 주요 목적은 논블로킹을 처리하고 성능을 향상시키는 것입니다. 작업에 다음과 같이 여러 비동기 함수 작업이 필요한 경우를 상상해 보세요.
async(1, function(item){ async(item, function(item){ async(item, function(item){ console.log('To be continued..'); }); }); });
읽기가 좀 어렵지 않나요?
또 다른 예로, 위 코드를 더욱 강력하게 만들기 위해 예외 캡처를 추가할 수 있습니다. 비동기 모드에서는 예외 처리가 다양한 콜백 함수에 분산되어 호출 시 try...catch를 통해 예외를 처리할 수 없으므로 효과적이고 명확하게 처리하기가 어렵습니다.
야, 어떡하지?
붐붐붐붐붐붐- 약속이 데뷔합니다.
ES6 Promise를 사용하여 위 코드를 최적화하면 다음을 얻을 수 있습니다.
function opration(item){ var p = new Promise(function(resolve, reject){ setTimeout(function(){ resolve(item+1); },1000); }); console.log(item); return p; } function failed(e){ console.log(e); } Promise.resolve(1).then(opration).then(opration).then(opration).catch(failed);
Promise를 사용하여 코드를 최적화하면 콜백 함수를 전환할 수 있다는 이점이 분명합니다. 체인 호출에 추가하고, 중첩 레이어를 피하고, 프로그램 흐름을 명확하게 만들고, catch 메서드를 통해 하나 이상의 콜백 함수에서 발생하는 오류를 균일하게 처리합니다.
아, 그렇군요. 그런데 ES6의 Promise는 누구이며 구체적인 사용 규칙은 무엇인가요? 함께 탐구해 봅시다.
2. Promise 개요
Promise는 기존 솔루션(콜백 및 이벤트)보다 합리적인 비동기 프로그래밍 솔루션입니다. 더 강력해졌습니다. ES6는 이를 언어 표준에 작성하고 사용법을 통일했으며 기본적으로 Promise 객체를 제공했습니다.
Promise 객체에는 세 가지 상태만 있습니다:
1, 보류 중: 비동기 작업이 완료되지 않았습니다.
2. 해결됨: 비동기 작업이 완료되었습니다.
3. 거부됨: 비동기 작업이 실패했습니다.
게다가 이 세 가지 상태에는 두 가지 변경 모드만 있으며, 일단 상태가 변경되면 다시 변경되지 않습니다.
보류 중인 비동기 작업.
2. 비동기 작업이 보류 상태에서 거부됨
그렇습니다. ES6 사양에 속하므로 크롬을 통해 Promise를 직접 인쇄할 수 있습니다. 이것 좀 보세요:
음, Promise가 생성자라는 것이 한눈에 분명합니다. Ook, 이를 통해 인스턴스화할 수 있습니다. 우리 자신의 Promise 객체를 만들고 이를 활용합니다.
3. Promise 시작하기 안내
Promise는 생성자이므로 먼저 새로운 것을 살펴보겠습니다.
var p = new Promise();
라고 입력하고 위 코드를 실행하면 크롬 스크린샷은 다음과 같습니다.
왜 오류가 보고되나요?
그런데 Promise 생성자는 매개변수로 함수를 필요로 하며, 매개변수로 사용되는 함수에는 두 개의 매개변수가 있습니다. 첫 번째 매개변수의 기능은 비동기 작업이 보류 중에서 해결됨으로 변경되는 경우입니다. 두 번째 매개변수는 비동기 작업이 보류 중에서 거부로 변경될 때 호출됩니다.
예를 들어, 익명 함수의 첫 번째 매개변수에 Resolve라는 이름을 지정했습니다. 데모는 다음과 같습니다:
var p = new Promise(function(resolve, reject){ console.log('new一个Promise对象'); setTimeout(function(){ resolve('Monkey'); },1000); });
위의 코드를 실행합니다. Chrome 스크린샷은 다음과 같습니다:
특별 알림: 익명 함수를 생성자로 전달할 때 Promise 함수의 매개변수로 new를 사용하면 위 그림과 같이 익명 함수가 이미 실행된 상태입니다.
안녕하세요, 위 코드에서는 익명 함수에 setTimeout 타이머를 사용하고 1초 후에 해결을 호출합니다. 왜 정의되지 않았거나 오류가 보고되지 않습니까? !
이것이 약속의 힘입니다. 이 때문에 비동기 작업을 우아한 체인 호출로 다시 작성할 수 있습니다. 어떻게 부르나요?
"Promise 개요" 섹션에서 크롬을 통해 Promise를 인쇄하고 빨간색 선 프레임 안의 영역을 사용했던 것을 기억하시나요? 그 중 Promise 프로토타입에 then 메소드(Promise.prototype.then)가 있는데, 이 then 메소드를 통해서면 충분합니다. 다음과 같습니다:
p.then(function(value){ console.log(value); });
그 중 then 메소드에는 Promise의 해결 및 거부 매개변수에 해당하는 두 개의 익명 함수가 매개변수로 있습니다. 코드를 실행해 보면 다음과 같습니다.
好了,当then执行完后,如果我们想继续在其之后看,使用then方法链式调用,有两种情况,一种是直接返回非Promise对象的结果;另一种是返回Promise对象的结果。
1、返回非Promise对象的结果:紧跟着的then方法,resolve立刻执行。并可使用前一个then方法返回的结果。如下:
p.then(function(value){ console.log(value); //返回非Promise对象,如我的对象 return { name: 'Dorie', age: 18 }; }).then(function(obj){ console.log(obj.name); });
执行上述完整代码,chrome截图如下:
2、返回Promise对象的结果:紧跟着的then方法,与new Promise后的then方法一样,需等待前面的异步执行完后,resolve方可被执行。如下:
p.then(function(value){ var p = new Promise(function(resolve, reject){ setTimeout(function(){ var message = value + ' V Dorie' resolve(message); },1000); }); console.log(value); //返回一个Promise对象 return p; }).then(function(value){ console.log(value); });
执行上述完整代码,chrome截图如下:
那么,当创建、执行Promise方法中有异常报错,如何捕获呢?
Promise.prototype.catch原型方法,就是为其而设定的。它具有冒泡的特性,比如当创建Promise实例时,就出错了,错误消息就会通过链式调用的这条链,一直追溯到catch方法,如果找到尽头都没有,就报错,并且再找到catch之前的所有then方法都不能执行了。Demo如下(代码太长,请自行展开):
<!DOCTYPE html> <head> <title>test</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> </head> <body> <script> var p = new Promise(function(resolve, reject){ //M未定义 console.log(M); setTimeout(function(){ resolve('Monkey'); },1000); }); p.then(function(value){ var p = new Promise(function(resolve, reject){ setTimeout(function(){ var message = value + ' V Dorie' resolve(message); },1000); }); console.log(value); //返回一个Promise对象 return p; }).then(function(value){ console.log(value); return 'next is catch'; }).catch(function(e){ console.log(e); }).then(function(value){ console.log('execute,but value is ' + value); }); </script> </body> </html>
执行上述代码,chrome截图如下:
好了,到这里,我们已经了解了最常用的Promise.prototype.then和Promise.prototype.catch这两个原型方法。另外,像Promise构造函数还有属于自身的方法,如all、rece、resolve、reject等,详情请点击这里(here)。
通过一路上对Promise的讲述,我们也有了一定的认识,其实Promise并没有想象中的那么难以理解嘛。懂得Promise概念后,其实我们自己也可以实现一个简易版的Promise。下面就一同尝试实现一个呗。
四、模拟Promise
假设:有三个异步操作方法f1,f2,f3,且f2依赖于f1,f3依赖于f2。如果,我们采用ES6中Promise链式调用的思想,我们可以将程序编写成这样:
f1().then(f2).then(f3);
那么,通过上面这一系列链式调用,怎样才能达到与ES6中Promise相似的功能呢?
初步想法:首先将上述链式调用的f2、f3保存到f1中,当f1中的异步执行完后,再调用执行f2,并将f1中的f3保存到f2中,最后,等f2中的异步执行完毕后,调用执行f3。详细构思图,如下:
从上图可知,由于f1、f2 、f3是可变得,所以存储数组队列thens,可放入,我们即将创建的模拟Promise构造函数中。具体实现代码如下:
//模拟Promise function Promise(){ this.thens = []; }; Promise.prototype = { constructor: Promise, then: function(callback){ this.thens.push(callback); return this; } };
并且,需要一个Promise.prototype.resolve原型方法,来实现:当f1异步执行完后,执行紧接着f1后then中的f2方法,并将后续then中方法,嫁接到f2中,如f3。具体实现代码如下:
//模拟Promise,增加resolve原型方法 function Promise(){ this.thens = []; }; Promise.prototype = { constructor: Promise, then: function(callback){ this.thens.push(callback); return this; }, resolve: function(){ var t = this.thens.shift(), p; if(t){ p = t.apply(null,arguments); if(p instanceof Promise){ p.thens = this.thens; } } } };
测试代码(代码太长,自行打开并运行)。
function f1() { var promise = new Promise(); setTimeout(function () { console.log(1); promise.resolve(); }, 1500) return promise; } function f2() { var promise = new Promise(); setTimeout(function () { console.log(2); promise.resolve(); }, 1500); return promise; } function f3() { var promise = new Promise(); setTimeout(function () { console.log(3); promise.resolve(); }, 1500) return promise; } f1().then(f2).then(f3);
仔细品味,上述实现的Promise.prototype.resolve方法还不够完美,因为它只能够满足于f1、f2、f3等方法都是使用模拟的Promise异步执行的情况。而,当其中有不是返回的Promise对象的呢,而是返回一个数字,亦或是什么也不返回,该怎么办?所以,针对以上提出的种种可能,再次改进resolve。改善代码如下:
//模拟Promise,改善resolve原型方法 var Promise = function () { this.thens = []; }; Promise.prototype = { constructor: Promise, then: function(callback){ this.thens.push(callback); return this; }, resolve: function () { var t,p; t = this.thens.shift(); t && (p = t.apply(null, arguments)); while(t && !(p instanceof Promise)){ t = this.thens.shift(); t && (p = t.call(null, p)); } if(this.thens.length){ p.thens = this.thens; }; } }
测试代码(代码太长,自行打开并运行)。
function f1() { var promise = new Promise(); setTimeout(function () { console.log(1); promise.resolve(); }, 1500) return promise; } function f2() { var promise = new Promise(); setTimeout(function () { console.log(2); promise.resolve(); }, 1500); return promise; } function f3() { var promise = new Promise(); setTimeout(function () { console.log(3); promise.resolve(); }, 1500) return promise; } function f4() { console.log(4); return 11; } function f5(x) { console.log(x+1); } function f6() { var promise = new Promise(); setTimeout(function () { console.log(6); promise.resolve(); }, 1500) return promise; } function f7() { console.log(7); } var that = f1().then(f2).then(f3).then(f4).then(f5).then(f6).then(f7);
好了,初步模拟的Promise就OK啦。
吼吼,对于Promise,我们这一路走来,发现原来也不过如此呢。
以上就是详细介绍JavaScript 中的 Promise的内容,更多相关内容请关注PHP中文网(www.php.cn)!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











WebSocket 및 JavaScript를 사용하여 온라인 음성 인식 시스템을 구현하는 방법 소개: 지속적인 기술 개발로 음성 인식 기술은 인공 지능 분야의 중요한 부분이 되었습니다. WebSocket과 JavaScript를 기반으로 한 온라인 음성 인식 시스템은 낮은 대기 시간, 실시간, 크로스 플랫폼이라는 특징을 갖고 있으며 널리 사용되는 솔루션이 되었습니다. 이 기사에서는 WebSocket과 JavaScript를 사용하여 온라인 음성 인식 시스템을 구현하는 방법을 소개합니다.

WebSocket과 JavaScript: 실시간 모니터링 시스템 구현을 위한 핵심 기술 서론: 인터넷 기술의 급속한 발전과 함께 실시간 모니터링 시스템이 다양한 분야에서 널리 활용되고 있다. 실시간 모니터링을 구현하는 핵심 기술 중 하나는 WebSocket과 JavaScript의 조합입니다. 이 기사에서는 실시간 모니터링 시스템에서 WebSocket 및 JavaScript의 적용을 소개하고 코드 예제를 제공하며 구현 원칙을 자세히 설명합니다. 1. 웹소켓 기술

JavaScript 및 WebSocket을 사용하여 실시간 온라인 주문 시스템을 구현하는 방법 소개: 인터넷의 대중화와 기술의 발전으로 점점 더 많은 레스토랑에서 온라인 주문 서비스를 제공하기 시작했습니다. 실시간 온라인 주문 시스템을 구현하기 위해 JavaScript 및 WebSocket 기술을 사용할 수 있습니다. WebSocket은 TCP 프로토콜을 기반으로 하는 전이중 통신 프로토콜로 클라이언트와 서버 간의 실시간 양방향 통신을 실현할 수 있습니다. 실시간 온라인 주문 시스템에서는 사용자가 요리를 선택하고 주문을 하면

WebSocket과 JavaScript를 사용하여 온라인 예약 시스템을 구현하는 방법 오늘날의 디지털 시대에는 점점 더 많은 기업과 서비스에서 온라인 예약 기능을 제공해야 합니다. 효율적인 실시간 온라인 예약 시스템을 구현하는 것이 중요합니다. 이 기사에서는 WebSocket과 JavaScript를 사용하여 온라인 예약 시스템을 구현하는 방법을 소개하고 구체적인 코드 예제를 제공합니다. 1. WebSocket이란 무엇입니까? WebSocket은 단일 TCP 연결의 전이중 방식입니다.

JavaScript 및 WebSocket: 효율적인 실시간 일기 예보 시스템 구축 소개: 오늘날 일기 예보의 정확성은 일상 생활과 의사 결정에 매우 중요합니다. 기술이 발전함에 따라 우리는 날씨 데이터를 실시간으로 획득함으로써 보다 정확하고 신뢰할 수 있는 일기예보를 제공할 수 있습니다. 이 기사에서는 JavaScript 및 WebSocket 기술을 사용하여 효율적인 실시간 일기 예보 시스템을 구축하는 방법을 알아봅니다. 이 문서에서는 특정 코드 예제를 통해 구현 프로세스를 보여줍니다. 우리

사용법: JavaScript에서 insertBefore() 메서드는 DOM 트리에 새 노드를 삽입하는 데 사용됩니다. 이 방법에는 삽입할 새 노드와 참조 노드(즉, 새 노드가 삽입될 노드)라는 두 가지 매개 변수가 필요합니다.

JavaScript 튜토리얼: HTTP 상태 코드를 얻는 방법, 특정 코드 예제가 필요합니다. 서문: 웹 개발에서는 서버와의 데이터 상호 작용이 종종 포함됩니다. 서버와 통신할 때 반환된 HTTP 상태 코드를 가져와서 작업의 성공 여부를 확인하고 다양한 상태 코드에 따라 해당 처리를 수행해야 하는 경우가 많습니다. 이 기사에서는 JavaScript를 사용하여 HTTP 상태 코드를 얻는 방법과 몇 가지 실용적인 코드 예제를 제공합니다. XMLHttpRequest 사용

JavaScript는 웹 개발에 널리 사용되는 프로그래밍 언어인 반면 WebSocket은 실시간 통신에 사용되는 네트워크 프로토콜입니다. 두 가지의 강력한 기능을 결합하면 효율적인 실시간 영상 처리 시스템을 만들 수 있습니다. 이 기사에서는 JavaScript와 WebSocket을 사용하여 이 시스템을 구현하는 방법을 소개하고 구체적인 코드 예제를 제공합니다. 첫째, 실시간 영상처리 시스템의 요구사항과 목표를 명확히 할 필요가 있다. 실시간 이미지 데이터를 수집할 수 있는 카메라 장치가 있다고 가정해 보겠습니다.
