에 속하는 async는 es6의 새로운 기능으로, 프로그램에 비동기 프로세스가 있을 수 있음을 나타내는 데 사용됩니다. async 키워드로 선언된 함수는 Promise 객체를 반환합니다. 함수에 직접 값이 반환되면 async는 비동기 함수가 값을 반환하지 않을 때 Promise.resolve()를 통해 직접 값을 Promise 객체로 캡슐화합니다. " Promise.resolve(정의되지 않음)"을 반환합니다.
이 튜토리얼의 운영 환경: Windows 7 시스템, ECMAScript 버전 6, Dell G3 컴퓨터.
먼저 이 두 키워드를 문자 그대로 이해해 보겠습니다. 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关键字修饰,使得代码按照顺序执行,即同步执行
(1)用于表明程序里面可能有异步过程
(2)async函数返回值的类型为Promise对象: 这是和普通函数本质上不同的地方,也是使用时重点注意的地方;
(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
(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的数据 }) }
(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 객체를 수정하는 데 사용됩니다.(1)은 프로그램에 비동기 프로세스가 있을 수 있음을 나타내는 데 사용됩니다//原本的解决方案 //第二个请求依赖于第一个请求的返回值,第三个请求依赖于第二个请求的返回值 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) //同理 //这样子写的代码更加的美观,并且更符合我们平时编写代码的习惯rrreeerrreee2. 비동기 키워드
(2) 비동기 함수 반환 값의 유형은 Promise 개체입니다. 일반적인 함수와는 다릅니다.
🎜 (3) 대기 없음, 비차단: async 키워드로 선언된 함수에 비동기 프로세스가 있는 경우 기다릴 수 있지만 함수 자체는 반환됩니다. 즉시 현재 메인 스레드를 차단하지 않습니다. wait 키워드로 수정된 비동기 프로세스가 함수에 사용되면 해당 코루틴에서 작동하고 반환하기 전에 비동기 작업이 완료될 때까지 차단하고 기다립니다. 🎜rrreee🎜🎜3. wait 키워드🎜🎜🎜 (1) wait는 비동기 함수 내에서만 사용할 수 있습니다. 일반 함수 내에 배치할 수 없습니다. 그렇지 않으면 오류가 보고됩니다. 🎜🎜 (2) wait 키워드 뒤에는 Promise 개체가 옵니다. 뒤에 함수가 오면 이 함수는 Promise 객체를 반환해야 합니다. 뒤에 Promise가 아닌 객체가 오면 Promise.resolve() 함수를 통해 자동으로 Promise 객체로 패키징되고 이행 상태가 됩니다. 🎜rrreee🎜 (3) Wait의 본질은 수정한 Promise 객체의 성취 상태를 기다리고, 해결(data)의 데이터를 반환하는 것입니다. 🎜🎜await 뒤에
- return newPromise(), 이 사용법은 async 함수의 원래 의도와 일치합니다. li>return data, 특히 이와 같이 작성하는 것은 Promise.resolve(data)와 동일하며 반환된 데이터는 Promise 객체로 캡슐화되지만 async 함수가 호출되면 반환 값 데이터는 간단한 =를 통해 얻을 수 없습니다. , 반환 값이 Promise 객체이기 때문에 이 데이터를 얻으려면 .then(data = > { })를 사용해야 합니다.
- 반환 값이 없으면 Promise를 반환하는 것과 동일합니다. .resolve(undefine);
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 중국어 웹사이트의 기타 관련 기사를 참조하세요!