ES6 - Async 와 비동기 프로 그래 밍 (11)

단일 스 레 드 는 자바 script 언어의 가장 본질 적 인 특성 중 하나 로 자바 script 엔진 이 js 코드 를 실행 할 때 같은 시간 에 하나의 작업 만 수행 할 수 있 습 니 다.
이런 모델 의 장점 은 실현 이 비교적 간단 하고 집행 환경 이 상대 적 으로 단순 하 다 는 것 이다.
나 쁜 점 은 한 가지 임무 가 오래 걸 리 면 뒤의 임 무 는 줄 을 서서 기 다 려 야 하 며 전체 프로그램의 집행 을 지연 시 킬 수 있다 는 것 이다.흔히 볼 수 있 는 브 라 우 저 응답 (가사) 이 없 는 이 유 는 자바 script 코드 가 장시간 실행 되 기 때 문 입 니 다. (예 를 들 어 순환) 전체 페이지 가 이 곳 에 걸 려 있 고 다른 작업 을 수행 할 수 없습니다.
그래서 비동기 프로 그래 밍 은 자 바스 크 립 트 언어 에 너무 중요 합 니 다.
어떤 동료 들 은 아직 '비동기' 를 잘 이해 하지 못 할 수도 있다.
이른바 '비동기' 란 하나의 임무 가 두 단락 으로 나 뉘 어 첫 단락 을 먼저 집행 한 다음 에 다른 임 무 를 집행 하고 준 비 를 다 한 후에 두 번 째 단락 을 고 개 를 돌려 집행 하 는 것 이다.
예 를 들 어 파일 을 읽 고 처리 하 는 작업 이 있 습 니 다. 작업 의 첫 번 째 단 계 는 운영 체제 에 파일 을 읽 어 달라 고 요청 하 는 것 입 니 다.그 다음 에 프로그램 은 다른 임 무 를 수행 하고 운영 체제 가 파일 로 돌아 갈 때 까지 기 다 렸 다가 작업 의 두 번 째 단계 (파일 처리) 를 수행 합 니 다.이런 불 연속 적 인 집행 을 비동기 라 고 한다.
이에 따라 연속 적 인 집행 을 동기 화 라 고 한다.연속 실행 이기 때문에 다른 작업 을 삽입 할 수 없 기 때문에 운영 체제 가 하 드 디스크 에서 파일 을 읽 는 동안 프로그램 은 기다 릴 수 밖 에 없습니다.
통속 적 으로 말 하 다.
주자 청 의 '뒷모습' 에서 아버 지 는 주자 청 에 게 "귤 몇 개 사 올 게. 너 여기 있어. 움 직 이지 마." 라 고 말씀 하 셨 다.
주자 청 은 움 직 이지 않 고 귤 을 사 오신 아버지 가 함께 귤 을 먹 기 를 기다 리 는 것 을 동기 라 고 한다.
만약 주자 청 이 아버 지 를 기다 리 지 않 고 혼자 떠 났 다 면 아버지 와 함께 귤 을 먹 을 수 없 었 을 것 이다.
1. 비동기 프로 그래 밍
우 리 는 사용자 가 이 매우 흔히 볼 수 있 는 장면 을 등록 하 는 것 을 예 로 들 어 비동기 프로 그래 밍 을 이야기 합 니 다.
첫 번 째 단계, 사용자 등록 여 부 를 검증 합 니 다.
두 번 째 단 계 는 등록 되 지 않 았 습 니 다. 인증 코드 를 보 냅 니 다.
세 번 째 단 계 는 인증 코드, 비밀 번 호 를 작성 하고 인증 코드 가 정확 한 지 확인 합 니 다.
이 과정 은 일정한 순서 가 있 으 니, 너 는 반드시 지난 단계 의 완성 을 보증 해야만 다음 단 계 를 순조롭게 진행 할 수 있다.
1.1 반전 함수
function testRegister(){}  //         
function sendMessage(){}   //         x
function testMessage(){}   //          

function doRegister(){  //    
    testRegister(data){
        if(data===false){ //   
            
        }else{ //   
             sendMessage(data){
                 if(data===true){ //       
                    testMessage(data){
                        if(data===true){  //     
                           
                        }else{  //      
                            
                        }
                    }    
                }
            }
        }
    }
}

코드 에 이미 많은 문제 가 있 습 니 다. 예 를 들 어 복잡 한 if 판단 문, 층 층 이 포 함 된 함수 로 인해 코드 의 가 독성 이 떨 어 지고 유지 하기 어렵 습 니 다.
또한, 층 층 반전 함수 에 이상 이 생기 면 디 버 깅 은 매우 사람 을 무 너 뜨 린 다. try - catch 는 비동기 의 이상 을 포착 할 수 없 기 때문에 우 리 는 debugger 를 계속 써 서 추적 할 수 밖 에 없 기 때문에 정말 놀 라 운 일이 다.
이런 겹겹이 끼 워 넣 은 것 을 반전 지옥 이 라 고 부른다.
1.2 Promise 방식
Promise 는 지옥 반환 문 제 를 해결 하기 위해 제 기 된 것 이다.이것 은 새로운 문법 기능 이 아니 라 새로운 쓰기 입 니 다. 리 셋 함수 의 끼 워 넣 기 를 체인 호출 으로 바 꿀 수 있 습 니 다.Promise 를 사용 하여 여러 파일 을 연속 으로 읽 습 니 다. 쓰 기 는 다음 과 같 습 니 다.
let state=1;  //      
function step1(resolve,reject){
    console.log('1.         ');
    if(state==1){
        resolve('   ');
    }else{
        reject('   ');
    }
}
function step2(resolve,reject){
    console.log('2.        ');
    if(state==1){
        resolve('    ');
    }else{
        reject('    ');
    }
}
function step3(resolve,reject){
    console.log('3.         ');
     if(state==1){
        resolve('     ');
    }else{
        reject('      ');
    }
}

new Promise(testRegister).then(function(val){ //         
    console.log(val);
    return new Promise(sendMessage);   //         
}).then(function(val){
     console.log(val);
    return new Promise(testMessage);  //          
}).then(function(val){
    console.log(val);
    return val;
});

리 셋 함 수 는 포 함 된 방식 으로 testRegister (), sendmessage (), testmessage () 를 순서대로 호출 하고 Promise 는 then 을 사용 하여 연결 합 니 다.
리 셋 함수 에 비해 Promise 코드 는 가 독성 이 높 고 코드 의 실행 순 서 는 일목요연 하 다.
Promise 의 방식 은 지옥 으로 되 돌아 가 는 것 을 해 결 했 지만 가장 큰 문 제 는 코드 가 불필요 하 다 는 것 이다. 원래 의 임 무 는 Promise 에 의 해 포장 되 었 다. 어떤 조작 이 든 한눈 에 보면 then 이 고 원래 의 의 미 를 잘 모 르 게 되 었 다.코드 프로 세 스 는 실행 프로 세 스 를 잘 표시 할 수 없습니다.
여러분 들 은 중학교 때 회 로 를 배 운 적 이 있 습 니 다. 이것 은 회로 의 직렬 연결 과 같 습 니 다. 만약 에 배 운 적 이 없어 도 괜 찮 습 니 다. jquery 가 체인 조작 이 있다 는 것 을 알 고 있 을 것 입 니 다. 이것 은 체인 조작 과 유사 하고 우리 의 사고 논리 에 비교적 부합 합 니 다.
1.3 async / await 방식
async 문법 은 new Promise 에 대한 포장 이 고 await 문법 은 then 방법 에 대한 추출 입 니 다.
 async function doRegister(url) {
  let data  = await testRegister();     //         
  let data2 = await sendMessage(data);  //         
  let data3 = await testMessage(data2); //          
  return data3
}

위의 코드 는 짧 지만 한 마디 한 마디 가 매우 중요 하 다.data 는 await test Register 의 반환 결과 입 니 다. data 2 는 data 를 sendmessage 의 매개 변수 로 사 용 했 고 data 3 은 data 2 를 testmessage 의 매개 변수 로 사 용 했 습 니 다.
doRegister 앞 에 키워드 async 를 추가 하면 함수 내 비동기 작업 전에 await 성명 을 추가 하면 됩 니 다.이 추가 키 워드 를 무시 하면 완전 동기 화 기법 이다.
2. async 용법
2.1 Promise 대상 으로 돌아 가기
async 함수 가 Promise 대상 을 되 돌려 줍 니 다.
async 함수 내부 return 문 구 를 되 돌려 주 는 값 은 then 방법 으로 함수 의 매개 변수 가 됩 니 다.
async function f() {
  return 'aaa';
}

f().then(v => console.log(v))
//aaa
//Promise {: undefined}


2.2 대기 명령
정상 적 인 상황 에서 await 명령 뒤 에는 Promise 대상 이 있 고 그 대상 의 결 과 를 되 돌려 줍 니 다.Promise 대상 이 아니라면 해당 값 을 바로 되 돌려 줍 니 다.
/*    */
async function f() {
  return await 123;
}
f().then(value => console.log(value));  // 123
/*    */
async function f() {
  return Promise.reject('error');
}
f().catch(e => console.error(e));   // error

주의사항:
await 명령 은 async 함수 에 만 사용 할 수 있 습 니 다. 일반 함수 에 사용 하면 오류 가 발생 합 니 다.
/*      */
function f(db) {
  let docs = [1, 2, 3];
  for(let doc of docs) {
    await db.push(doc);
  }
  return db; // Uncaught SyntaxError: Unexpected identifier
}





/*     (    ) */
async function f(db) {
  let docs = [1, 2, 3];
  for(let doc of docs) {
    await db.push(doc);
  }
  return db;
}


2.3 async 에서 이상 처리
async / await 를 사용 하면 try / catch 에 맞 춰 비동기 작업 과정 에서 의 문 제 를 포착 할 수 있 습 니 다. Promise 에서 reject 의 데 이 터 를 포함 합 니 다.
await 뒤에 reject 가 존재 할 수 있 습 니 다. try.. catch 코드 블록 에 있어 야 합 니 다.
async function f() {
  try {
    await Promise.reject('   ');
  } catch(e) {
    console.error(e);
  }
  return Promise.resolve('hello');
}
f().then(v => console.log(v));   //     hello

3. 병렬 연결 중인 await
async / await 문법 은 확실히 간단 하고 쓰기 좋 지만 잘못 사용 하기 쉬 우 며 구체 적 인 업무 장면 수요 에 따라 결정 해 야 한다.
예 를 들 어 우 리 는 그림 의 크기 정 보 를 가 져 와 야 한다.
async function allPicInfo (imgs) {
  const result = [];
  for (const img of imgs) {
    result.push(await getSize(img));
  }
}

코드 의 매번 getSize 호출 은 지난번 호출 이 완 료 될 때 까지 기 다 려 야 합 니 다. 마찬가지 로 성능 낭비 이 고 시간 도 오래 걸 립 니 다.같은 기능 은 이런 방식 으로 하면 더욱 적합 하 다.
async function allPicInfo (imgs) {
  return Promise.all(imgs.map(img => getSize(img)));
}

여러 비동기 작업 은 계승 관계 가 없 으 면 동시에 촉발 하 는 것 이 좋 습 니 다.
4. 총화
최초의 리 턴 함수 부터 Promise 대상 까지 매번 개선 되 었 으 나 철저 하지 못 하 다 고 느 꼈 다.그들 은 모두 추가 적 인 복잡성 을 가지 고 추상 적 인 바 텀 운영 체 제 를 이해 해 야 한다.
예 를 들 어 세 가지 요청 이 필요 합 니 다. 세 번 째 요청 은 두 번 째 요청 의 결과 에 의존 하고 두 번 째 요청 은 첫 번 째 요청 의 결과 에 의존 합 니 다.ES5 로 이 루어 지면 3 층 의 반전 이 있어 코드 의 횡적 발전 을 초래 할 수 있다.Promise 로 실현 하려 면 최소 3 개의 then 이 필요 하여 코드 의 수직 발전 을 초래 합 니 다.그러나 async / await 는 이 문제 들 을 해결 했다.
실현 을 보면 async / await 는 생 성기, Promise 를 바탕 으로 구 축 된 새로운 문법 이다. 생 성기 로 프로 세 스 제 어 를 실현 하고 Promise 로 비동기 제 어 를 실현 한다.
그러나 이 로 인해 async / await 를 얕 보지 말고 동기 화 방식 으로 비동기 코드 를 쓰 는 것 이 매우 강하 다.
async / await 는 의미 화, 코드 간소화, 오류 처리 등에 있어 많은 장점 을 가지 고 있 습 니 다. async / wait 로 조건 코드 를 작성 하 는 것 이 훨씬 간단 하고 같은 코드 구조 (잘 알려 진 try / catch 구문) 를 사용 하여 동기 화 와 비동기 오 류 를 처리 할 수 있 기 때문에 자바 스 크 립 트 비동기 프로 그래 밍 의 최종 해결 방안 이 라 고 불 리 며 그 중요성 과 장점 을 알 수 있 습 니 다.
젊은이 들 이 앞으로 실전 종목 에서 많이 연습 해 야 async / await 의 진정한 정 요 를 파악 할 수 있 기 를 바 랍 니 다.

좋은 웹페이지 즐겨찾기