>웹 프론트엔드 >프런트엔드 Q&A >비동기는 es6 속성입니까?

비동기는 es6 속성입니까?

青灯夜游
青灯夜游원래의
2022-10-20 15:01:541826검색

에 속하는 async는 es6의 새로운 기능으로, 프로그램에 비동기 프로세스가 있을 수 있음을 나타내는 데 사용됩니다. async 키워드로 선언된 함수는 Promise 객체를 반환합니다. 함수에 직접 값이 반환되면 async는 비동기 함수가 값을 반환하지 않을 때 Promise.resolve()를 통해 직접 값을 Promise 객체로 캡슐화합니다. " Promise.resolve(정의되지 않음)"을 반환합니다.

비동기는 es6 속성입니까?

이 튜토리얼의 운영 환경: Windows 7 시스템, ECMAScript 버전 6, Dell G3 컴퓨터.

ES6 새로운 기능 async 및 Wait 키워드

1. 사전 이해

먼저 이 두 키워드를 문자 그대로 이해해 보겠습니다. async는 asynchronous(비동기화)의 약어이며, wait는 wait의 약어로 간주할 수 있습니다. 따라서 async는 함수를 비동기식으로 선언하는 데 사용되는 반면, wait는 비동기 작업이 완료될 때까지 기다리는 데 사용되는 것으로 이해될 수 있습니다.

async 및 Wait 키워드를 사용하면 의도적으로 Promise를 연결하지 않고도 Promise 기반 비동기 동작을 보다 간결한 방식으로 작성할 수 있습니다.

다음으로 몇 가지 예를 통해 async의 기능을 미리 살펴보고 wait를 살펴보겠습니다.

지식 포인트 1: async 키워드로 선언된 함수는 Promise 객체를 반환합니다. 함수에서 직접 값을 반환하는 경우 async는 Promise.resolve()를 통해 직접 값을 Promise 객체로 캡슐화합니다. async 함수가 값을 반환하지 않으면 Promise.resolve(정의되지 않음)return 一个直接量,async 会把这个直接量通过 Promise.resolve() 封装成 Promise 对象。当 async 函数没有返回值时,返回 Promise.resolve(undefined)

 //定义一个普通函数,返回一个字符串
 function test() {
     return "hello async";
 }
 const result1 = test();
 console.log(result1); //输出一个字符串 hello async
 
 //定义一个使用了async修饰的函数,同样返回一个字符串
 async function testAsync() {
     return "hello async";
 }
 const result2 = testAsync();
 console.log(result2); //输出一个Promise对象 Promise {<fulfilled>: 'hello async'}
 //async较好的用法
 async function testAsync(){
     //返回一个Promise对象
     return new Promise((resolve, reject)=>{
         //处理异步任务
         setTimeout(function () {
             resolve("testAsync")
         }, 1000);
     })
 }
 //async通常用于声明一个处理异步任务且返回了Promise对象的函数

知识点2: await关键字只能使用在被async声明的函数内,用于修饰一个Promise对象,使得该Promise对象处理的异步任务在当前协程上按顺序同步执行。

 //定义一个使用async修饰的函数,处理异步任务
 async function testAsync(){
     return new Promise((resolve, reject)=>{
         setTimeout(function () {
             resolve("testAsync")
         }, 1000);
     })
 }
 //定义一个函数,直接调用testAsync函数
 function testAwait(){
     console.log('testAsync调用前')
     testAsync().then(res=>{
         console.log(res) //输出"testAsync"
     })
     console.log('testAsync调用后')
 }
 
 /***** 输出如下 *****/
 testAsync调用前
 testAsync调用后
 testAsync
 //尽管代码按顺序写,但不按顺序执行,因为testAsync()是异步函数
 //定义一个函数(不使用async声明该函数)用await修饰调用testAsync函数
 function testAwait(){
     console.log('testAsync调用前')
     await testAsync().then(res=>{ //使用await关键字修饰
         console.log(res)
     })
     console.log('testAsync调用后')
 }
 
 //调用testAwait()函数
 testAwait()
 //报错:Uncaught SyntaxError: await is only valid in async functions and the top level bodies of modules,因为await只能使用在被async修饰的函数内。
 //定义一个函数(使用async声明该函数)用await修饰调用testAsync函数
 async function testAwait(){
     console.log('testAsync调用前')
     await testAsync().then(res=>{
         console.log(res)
     })
     console.log('testAsync调用后')
 }
 
 /***** 输出如下 *****/
 testAsync调用前
 testAsync
 testAsync调用后
 
 //使用了await关键字修饰,使得代码按照顺序执行,即同步执行

2、async关键字

(1)用于表明程序里面可能有异步过程

(2)async函数返回值的类型为Promise对象: 这是和普通函数本质上不同的地方,也是使用时重点注意的地方;

  • return newPromise( ),这个用法符合async函数本意;
  • return data,特别注意到是这样子写相当于Promise.resolve(data),返回的data被封装成一个Promise对象,但是在调用async函数的地方通过简单的=是拿不到这个返回值data的,因为返回值是一个Promise对象,所以需要用.then(data => { })方式才可以拿到这个data;
  • 如果没有返回值,相当于返回了Promise.resolve(undefined);

(3)无等待,非阻塞:使用async关键字声明的函数里面如果有异步过程可能会等待,但是函数本身会马上返回,不会阻塞当前主线程。如果在函数里面使用了await关键字修饰的异步过程,其工作在相应的协程上,会阻塞等待异步任务的完成再返回。

 //定义一个函数,处理异步任务(使用定时器模拟),返回一个Promise对象
 async function testAsync(){
     return new Promise((resolve, reject) => {
       setTimeout(function () {
         resolve("成功调用testAsync")
       }, 1000);
     });
 }
 
 //定义一个函数,使用await关键字修饰调用testAsync()函数
 async function testAwait(){
     //使用了await关键字修饰调用testAsyn()函数
     await this.testAsync().then(res=>{
       console.log(res) //输出的是testAsync()函数resolve的值
     });
     console.log("helloAsync");
 }
 
 //主线程
 console.log('testAwait调用前')
 testAwait();
 console.log('testAwait调用后')
 
 /***** 输出结果如下 *****/
 testAwait调用前
 testAwait调用后 //因为testAwait()函数使用了async关键字修饰,所以不会阻塞主线程的执行,所以这两句话会先直接输出,然后再执行testAwait()函数
 成功调用testAsync //因为testAwait()函数在内部调用testAsync()函数时使用了await关键字修饰,所以在对应的协程上会阻塞,等待testAsync()函数执行完,再输出下面那句'helloAsync'
 helloAsync

3、await关键字

(1)await只能在async函数内部使用:不能放在普通函数里面,否则会报错。

(2)await关键字后面跟的是一个Promise对象。如果跟的是一个函数,则这个函数应当返回一个Promise对象。如果跟的是非Promise对象,则会通过Promise.resolve( )函数自动将这个东西包装成一个Promise对象并置于fulfilled状态。

 //例如:
 const a = await 'Hello Await'
 // 相当于
 const a = await Promise.resolve('Hello Await');
 
 console.log(a) //输出 'Hello Await'

(3)await的本质是等待它所修饰的Promise对象的fulfilled状态,并把resolve(data)的数据data返回。

意思是,如果await后面跟的是一个 Promise 对象,await 就会阻塞后面的代码,等着 Promise 对象 resolve,然后得到 resolve 的值,作为 await 表达式的运算结果。

 async function testAsync(){
     return new Promise((resolve, reject) => {
       setTimeout(function () {
         resolve("成功调用testAsync")
       }, 1000);
     });
 }
 
 const a = await testAsync() //这里的a就会拿到testAsync函数resolve的数据
 console.log(a) //在一秒后输出'成功调用testAsync'

(4)await并不关心它所修饰的Promise对象的rejected状态,即reject(data)的数据data并不会被await处理,所以建议通过Promise对象调用catch去捕获。

 async testAwait(){
     //变量a用于接收testAsync()函数resolve的数据
     let a = await testAsync().catch(err=>{
         //处理异常和reject的数据
     })    
 }

4、深入讲解async和await

(1)执行顺序

 //定义一个函数,该函数接收一个参数,1s后再返回参数的两倍
 async function double(num) {
     return new Promise((resolve, reject) => {
         setTimeout(() => { //使用定时器模拟异步任务
             resolve(2 * num) //将运算结果交给resolve
         }, 1000);
     })
 }
 
 async function getResult () {
     console.log('double调用前')  //顺序:2
     let result = await double(10); //将10作为参数传递给double函数
     //result变量用于接收double()函数resolve的值
     console.log(result); //顺序:4
     console.log('double调用后') //顺序:4
 }
 
 console.log('getResult调用前') //顺序:1
 getResult();
 console.log('getResult调用后') //顺序:3
 
 /***** 依次输出如下 *****/
 getResult调用前
 double调用前
 getResult调用后
 20 //1s后输出
 double调用后

①首先打印输出getResult调用前,同步代码,顺序执行;

②然后调用方法getResult( ),打印输出double调用前

 //方法一:通过promise对象的catch进行捕获
 function a(){
     return new Promise((resolve,reject) => {
         setTimeout(() => {
             reject("something")
         }, 1000)
     })
 }
 
 async function b(){
     let r = await a().catch((err)=>{
         console.log(err)
     })
 }
 //方法二:通过try/catch语句处理
 function a(){
     return new Promise((resolve,reject) => {
         setTimeout(() => {
             reject("something")
         }, 1000)
     })
 }
 
 async function b(){
     let r = null
     try{
        r = await a()
     }catch(err){
         console.log(err)
     }
 }

을 반환합니다. 지식 포인트 2:

wait 키워드는 함수에서만 사용할 수 있습니다. async Inside에 의해 선언되었으며, Promise 객체에 의해 처리되는 비동기 작업이 현재 코루틴에서 동기적이고 순차적으로 실행되도록 Promise 객체를 수정하는 데 사용됩니다.
 //原本的解决方案
 //第二个请求依赖于第一个请求的返回值,第三个请求依赖于第二个请求的返回值
 request1().then(function(data){ 
     return request2(data)
 }).then(function(data){ 
     return request3(data)
 })
 //这里只发送了三次请求,代码看起来还不错,虽然它已经比普通的回调函数形式好了很多。
 //那如果需要发送五次或十次请求呢?代码也许会没那么美观,接下来我们使用学习到的await去解决这个问题。
 //使用await的解决方案
 var res1 = await request1() //将request1的返回值赋值给res1
 var res2 = await request2(res1) //将res1作为参数传给request2,并将request2的返回值赋值给res2
 var res3 = await request3(res2) //同理
 
 //这样子写的代码更加的美观,并且更符合我们平时编写代码的习惯
rrreeerrreee

2. 비동기 키워드

(1)은 프로그램에 비동기 프로세스가 있을 수 있음을 나타내는 데 사용됩니다

(2) 비동기 함수 반환 값의 유형은 Promise 개체입니다. 일반적인 함수와는 다릅니다.

  • return newPromise(), 이 사용법은 async 함수의 원래 의도와 일치합니다. li>return data, 특히 이와 같이 작성하는 것은 Promise.resolve(data)와 동일하며 반환된 데이터는 Promise 객체로 캡슐화되지만 async 함수가 호출되면 반환 값 데이터는 간단한 =를 통해 얻을 수 없습니다. , 반환 값이 Promise 객체이기 때문에 이 데이터를 얻으려면 .then(data = > { })를 사용해야 합니다.
  • 반환 값이 없으면 Promise를 반환하는 것과 동일합니다. .resolve(undefine);
🎜 (3) 대기 없음, 비차단: async 키워드로 선언된 함수에 비동기 프로세스가 있는 경우 기다릴 수 있지만 함수 자체는 반환됩니다. 즉시 현재 메인 스레드를 차단하지 않습니다. wait 키워드로 수정된 비동기 프로세스가 함수에 사용되면 해당 코루틴에서 작동하고 반환하기 전에 비동기 작업이 완료될 때까지 차단하고 기다립니다. 🎜rrreee🎜🎜3. wait 키워드🎜🎜🎜 (1) wait는 비동기 함수 내에서만 사용할 수 있습니다. 일반 함수 내에 배치할 수 없습니다. 그렇지 않으면 오류가 보고됩니다. 🎜🎜 (2) wait 키워드 뒤에는 Promise 개체가 옵니다. 뒤에 함수가 오면 이 함수는 Promise 객체를 반환해야 합니다. 뒤에 Promise가 아닌 객체가 오면 Promise.resolve() 함수를 통해 자동으로 Promise 객체로 패키징되고 이행 상태가 됩니다. 🎜rrreee🎜 (3) Wait의 본질은 수정한 Promise 객체의 성취 상태를 기다리고, 해결(data)의 데이터를 반환하는 것입니다. 🎜🎜await 뒤에 Promise 개체가 오면 await는 다음 코드를 차단하고 Promise 개체 를 기다립니다. 해결을 수행한 다음 await 표현식의 결과로 resolve 값을 가져옵니다. 🎜rrreee🎜 (4) Wait는 수정하는 Promise 객체의 거부 상태에 대해 신경 쓰지 않습니다. 즉, 거부(data)의 데이터 데이터는 Wait에 의해 처리되지 않으므로 Promise 객체를 통해 catch를 호출하는 것이 좋습니다. 그것을 포착하기 위해. 🎜rrreee🎜🎜4. async 및 wait에 대한 심층 설명🎜🎜🎜 (1) 실행 순서🎜rrreee🎜 ① 먼저 getResult 호출 전을 인쇄하고 코드를 동기화한 후 순차적으로 실행합니다 🎜🎜. ②그런 다음 getResult( ) 메서드를 호출하고 double을 호출하기 전에 출력을 인쇄하고 동기 코드를 순차적으로 실행합니다. 🎜🎜3 그런 다음 비동기 메서드 double( )을 호출합니다.🎜🎜🎜여기에서 Wait 키워드가 사용되지 않으면, 순서대로의 출력은 다음과 같습니다. getResult 호출 전, double 호출 전, double 호출 후, getResult 호출 후, 1s 이후 20이 출력됩니다.🎜🎜비동기 작업은 다른 코드의 실행에 영향을 미치지 않기 때문에 다른 코드는 순서대로 실행되면 최종적으로 double 함수가 실행됩니다🎜 🎜🎜🎜 여기서는 wait 키워드를 사용하기 때문에 여기서 실행하면 getResult() 코드가 차단됩니다. double 함수가 해결될 때까지 기다렸다가 실행을 계속하세요🎜

④尽管getResult函数内部被await阻塞了,由于getResult函数本身也是个async函数,所以它不会影响getResult函数外面的代码执行。因为调用async函数不会造成阻塞,它内部的所有阻塞都被封装在一个Promise对象中异步执行。

⑤所以在调用getResult函数后,会继续向下执行,即打印输出getResult调用后

⑥当1s之后,异步函数double执行完成,将结果交给resolve。

⑦通过await关键字接收到double函数resolve的值,赋值给result变量。打印输出20

⑧因为使用了await阻塞将异步变为同步,所以在打印输出20后再打印输出double调用后

(2)处理reject回调

 //方法一:通过promise对象的catch进行捕获
 function a(){
     return new Promise((resolve,reject) => {
         setTimeout(() => {
             reject("something")
         }, 1000)
     })
 }
 
 async function b(){
     let r = await a().catch((err)=>{
         console.log(err)
     })
 }
 //方法二:通过try/catch语句处理
 function a(){
     return new Promise((resolve,reject) => {
         setTimeout(() => {
             reject("something")
         }, 1000)
     })
 }
 
 async function b(){
     let r = null
     try{
        r = await a()
     }catch(err){
         console.log(err)
     }
 }

(3)使用await优化Promise对象的回调地狱问题

在Promise章节中我们通过了Promise对象的then( )方法链式调用解决了回调地狱问题,但看起来仍然不够美观,我们可以通过await优化一下,让它看起来更符合我们平时代码的编写习惯。

 //原本的解决方案
 //第二个请求依赖于第一个请求的返回值,第三个请求依赖于第二个请求的返回值
 request1().then(function(data){ 
     return request2(data)
 }).then(function(data){ 
     return request3(data)
 })
 //这里只发送了三次请求,代码看起来还不错,虽然它已经比普通的回调函数形式好了很多。
 //那如果需要发送五次或十次请求呢?代码也许会没那么美观,接下来我们使用学习到的await去解决这个问题。

原本的要求是每个请求都依赖于上一个请求的返回值,那么是不是得等一个请求完,才能发送下一个请求?这时我们可以思考一下,await的作用是什么?是不是对一个Promise对象去进行阻塞,使其状态变为fulfilled后获取resolve的值。这不就正是我们所需要的。

 //使用await的解决方案
 var res1 = await request1() //将request1的返回值赋值给res1
 var res2 = await request2(res1) //将res1作为参数传给request2,并将request2的返回值赋值给res2
 var res3 = await request3(res2) //同理
 
 //这样子写的代码更加的美观,并且更符合我们平时编写代码的习惯

【相关推荐:javascript视频教程编程视频

위 내용은 비동기는 es6 속성입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.