Promise.all 깊이 이해

8036 단어 Promise.all
비동기 적 약속
Promise.all
Promise.all 이 받 은 promise 배열 은 순서대로 실 행 됩 니까?아니면 함께 실 행 됩 니까?즉,돌아 온 결 과 는 순서대로 고정 되 어 있 습 니까?
현재 두 가지 답 이 있다.
  • 은 동기 화 되 어야 하지만 효율 적 인 문제 가 있 습 니 다.비동기 실행 으로 바 꾸 려 면 어떻게 해 야 합 니까?
  • 어떤 사람들 은 결과 가 순서대로 집행 되 었 다 고 생각 하고,어떤 사람들 은 결과 순서 가 불확실 하 다 고 생각한다.
  • 그러면 우 리 는 실현 에 따라 복호화 한다.
    환경:
    
    vscode 1.20.1
    node  v8.9.0
    npm  v5.6.0
    실험 코드:
    
    //      ,toFixed         ,0     ,  ~1000
    const getRandom = () => +(Math.random()*1000).toFixed(0);
    
    const asyncTask = (taskID) => new Promise( (resolve) => {
      //       0~1000    
      let timeout = getRandom();
      //         ID  taskID=1 start.
      console.log(`taskID=${taskID} start.`);
      //       ,function()    () => {...}
      setTimeout(function() {
        //       taskID, timeout
        console.log(`taskID=${taskID} finished in time=${timeout}.`);
        //       
        resolve(taskID)
      }, timeout);
    });
    
    Promise.all([asyncTask(1),asyncTask(2),asyncTask(3)])
    .then(resultList => {
      console.log('results:',resultList);
    });
    실험 결 과 는 다음 과 같다.
    처음
    
    taskID=1 start.
    taskID=2 start.
    taskID=3 start.
    taskID=2 finished in time=321.
    taskID=3 finished in time=506.
    taskID=1 finished in time=932.
    results:
    Array(3) [1, 2, 3]
    두 번 째
    
    taskID=1 start.
    taskID=2 start.
    taskID=3 start.
    taskID=1 finished in time=243.
    taskID=3 finished in time=305.
    taskID=2 finished in time=792.
    results:
    Array(3) [1, 2, 3]
    세 번 째
    
    taskID=1 start.
    taskID=2 start.
    taskID=3 start.
    taskID=3 finished in time=380.
    taskID=1 finished in time=539.
    taskID=2 finished in time=782.
    results:
    Array(3) [1, 2, 3]
    보충 지식 소개:
    
    // toFixed()      Number               。
    NumberObject.toFixed(num)
    // num   。       ,  0 ~ 20     ,   0   
    // 20,               。        ,   0   。
    Promise 구조 함 수 는 하나의 매개 변수 만 있 습 니 다.이 매개 변 수 는 하나의 함수 로 실행 기 라 고 불 립 니 다.실행 기 는 2 개의 매개 변수 가 있 는데 각각 resolve()와 reject()입 니 다.하 나 는 성공 적 인 리 셋 을 나타 내 고 하 나 는 실 패 를 나타 내 는 리 셋 입 니 다.
    
    new Promise(function(resolve, reject) {
     setTimeout(() => resolve(5), 0)
    }).then(v => console.log(v)) // 5
    Promise 인 스 턴 스 는 resolve 나 reject 함수 로 만 되 돌아 갈 수 있 고 then()이나 catch()를 사용 하여 가 져 올 수 있 으 며 new Promise 에서 직접 return 할 수 없습니다.그러면 Promise 반환 값 을 가 져 올 수 없습니다.
    이 를 통 해 알 수 있 듯 이 Promise.all 의 퀘 스 트 목록 [asyncTask(1),asyncTask(2),asyncTask(3)] 은 순서대로 시 작 된 것 입 니 다.
    그러나 결과 에 따 르 면 이들 은 비동기 적 이 고 서로 막 히 지 않 으 며 모든 임무 의 완성 시 기 는 불확실 하 다.그럼 에 도 불구 하고 모든 임무 가 끝났다.
    그 후에 도 결 과 는 resultList 에 순서대로 매 핑 됩 니 다.그러면 Promise.all 의 작업 목록 과[asyncTask(1),asyncTask(2),asyncTask(3)] 을 일일이 대응 하 다.
    Promise.all()깊이 이해
    여기 서 어떤 사람들 은 잘 모 르 겠 지만,왜 배열 로 돌아 갑 니까?
    우 리 는 이 코드 를 좀 더 살 펴 보 자.
    
    Promise.all([asyncTask(1),asyncTask(2),asyncTask(3)])
    .then(resultList => {
      console.log('results:',resultList);
    });
    보통 우 리 는 이 보 를 사용 할 때 하나의 Promise 만 있 는데,지금 은 all()방법 으로 여러 개의 Promise 인 스 턴 스 를 포장 합 니 다.
    문법 은 매우 간단 하 다.매개 변 수 는 하나 뿐 이 고 대상 을 교체 할 수 있 으 며 배열 이나 Symbol 유형 등 이 될 수 있다.
    
    Promise.all(iterable).then().catch()
    Promise 인 스 턴 스 3 개 입력:
    
    Promise.all([
     new Promise(function(resolve, reject) {
      resolve(1)
     }),
     new Promise(function(resolve, reject) {
      resolve(2)
     }),
     new Promise(function(resolve, reject) {
      resolve(3)
     })
    ]).then(arr => {
     console.log(arr) // [1, 2, 3]
    })
    그럼 뒤 돌아 보면 알 겠 죠?
    우리 가 들 어 오 는 것 은 배열 이기 때문에 돌아 오 는 것 은 배열 이 어야 하 며,말 한 것 을 매 핑 할 것 입 니 다.
    Promise.race()
    문법 은 all()과 같 지만 반환 값 은 다 릅 니 다.race 는 들 어 오 는 여러 Promise 인 스 턴 스 에 따라 하나의 인 스 턴 스 resolve 나 reject 만 있 으 면 이 결과 만 되 돌려 주 고 다른 인 스 턴 스 는 실행 되 지 않 습 니 다.
    예 를 들 어 결 과 를 3 으로 되 돌려 줍 니 다.타 이 머 를 설 치 했 기 때문에 세 번 째 Promise 가 가장 빨리 실 행 됩 니 다.
    
    Promise.race([
     new Promise(function(resolve, reject) {
      setTimeout(() => resolve(1), 1000)
     }),
     new Promise(function(resolve, reject) {
      setTimeout(() => resolve(2), 100)
     }),
     new Promise(function(resolve, reject) {
      setTimeout(() => resolve(3), 10)
     })
    ]).then(value => {
     console.log(value) // 3
    })
    비동기 화 는 왜 화살표 함 수 를 사용 합 니까?
    이것 은 내 가 줄곧 곤 혹 스 러 워 하 는 원인 이다.우 리 는 앞의 예 를 개조 할 것 이다.
    다음 과 같다.
    
    const getRandom = () => +(Math.random()*1000).toFixed(0);
    
    function test(taskID) {
     new Promise( (resolve) => {
      //       0~1000    
      let timeout = getRandom();
      //         ID 
      console.log(`taskID=${taskID} start.`);
      setTimeout(function() {
        console.log(`taskID=${taskID} finished in time=${timeout}.`);
        resolve(taskID)
      }, timeout);
    } )
    }
    
    Promise.all([test(1),test(2),test(3)])
    .then(resultList => {
      console.log('results:',resultList);
    });
    일단 결과 가 어떻게 되 는 지 볼 까요?
    첫 번 째:
    
    taskID=1 start.
    taskID=2 start.
    taskID=3 start.
    results:
    Array(3) [undefined, undefined, undefined]
    taskID=1 finished in time=460.
    taskID=2 finished in time=704.
    taskID=3 finished in time=883.
    두 번 째:
    
    taskID=1 start.
    taskID=2 start.
    taskID=3 start.
    results:
    Array(3) [undefined, undefined, undefined]
    taskID=2 finished in time=17.
    taskID=3 finished in time=212.
    taskID=1 finished in time=612.
    세 번 째:
    
    taskID=1 start.
    taskID=2 start.
    taskID=3 start.
    results:
    Array(3) [undefined, undefined, undefined]
    taskID=3 finished in time=130.
    taskID=1 finished in time=256.
    taskID=2 finished in time=593.
    실험 은 적어도 세 번 이상 해 야 설득력 이 있다.
    출력 결 과 를 통 해 되 돌아 오 는 배열 의 데 이 터 는 모두 undefined 임 을 알 수 있 습 니 다.우 리 는 이 원인 을 찾 아야 한다.그것 은 왜 화살표 함 수 를 사용 해 야 하 는 지 찾 은 것 이다.
    우선 디 버 깅 을 통 해 찾 아 보 겠 습 니 다.
    그림:

    프로그램 이 먼저 인쇄 되 었 다.
    taskID=1 start.
    taskID=2 start.
    taskID=3 start.
    설명 은 무조건 먼저 했 어 요.
    
    console.log(`taskID=${taskID} start.`);
    그래서 우 리 는 이 단락 에서 정지점 을 쳐 서 한 걸음 한 걸음 디 버 깅 을 한다.다음 과 같다.

    위의 그림 에서 볼 수 있 듯 이 console.log(taskID=${taskID} start.)는 매번 실 행 됩 니 다.setTimeout 도 실 행 됩 니 다.그러나 세 번 후에 바로 실 행 됩 니 다.then().그래서 우 리 는 이 유 를 찾 았 습 니 다.Promise.all()은 이때 완전한 증거 로 돌아 가 기 를 기다 리 지 않 고 실 행 했 습 니 다.then()은 resolve 를 기다 리 지 않 고 실 행 했 습 니 다.
    이 안에 이상 이 생 겼 다 는 것 을 설명 합 니 다.이 이상 은 바로 Promise.all()안의 매개 변수 로 함수 가 존재 하기 때문에 this 가 헷 갈 리 기 때문에 우 리 는 대상 을 사용 해 야 합 니 다.더욱 정확 한 표현 은 바로 인 스 턴 스 입 니 다.
    주의:
    이 코드 를 예 로 들 면:
    
    var p1 = Promise.resolve(1),
      p2 = Promise.resolve(2),
      p3 = Promise.resolve(3);
    Promise.all([p1, p2, p3]).then(function (results) {
      console.log(results); // [1, 2, 3]
    });
    위의 방법 에서 promise 배열 의 모든 promise 인 스 턴 스 가 resolve 로 바 뀌 었 을 때 이 방법 은 되 돌아 오고 모든 결 과 를 results 배열 에 전달 합 니 다.promise 배열 의 모든 promise 가 reject 이면 전체 Promise.all 호출 이 즉시 종료 되 고 reject 의 새로운 promise 대상 을 되 돌려 줍 니 다.reject 사용 예 는 다음 과 같 습 니 다.
    
    var p1 = Promise.resolve(1),
      p2 = Promise.reject(2),
      p3 = Promise.resolve(3);
    Promise.all([p1, p2, p3]).then(function (results) {
      //then       
      console.log(results); 
    }).catch(function (e){
      //catch       ,     :2
      console.log(2);
    });
    이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

    좋은 웹페이지 즐겨찾기