제14장 Promise 대상

7228 단어

1. Promise의 의미


Promise는 리셋 함수와 이벤트 감청보다 훨씬 합리적이고 강력한 비동기 프로그래밍 솔루션입니다.쉽게 말하면 Promise는 하나의 용기로서 그 안에 어떤 미래가 끝날 수 있는 사건(보통 비동기적인 조작)의 결과를 보존하고 있다.
두 가지 특징이 있다. (1) 대상의 상태는 외부의 영향을 받지 않는다.Promise 대상은 세 가지 상태가 있는데 그것이 바로 pending (진행 중),fulfilled (성공),rejected (실패) 이다.비동기 조작의 결과만 현재 어떤 상태인지 결정할 수 있으며, 그 어떠한 다른 조작도 이 상태를 바꿀 수 없다
(2) 컨디션이 바뀌면 더 이상 변하지 않는다. 언제든지 이 결과를 얻을 수 있다.
Promise 대상이 있으면 비동기 조작을 동기화 조작의 절차로 표현할 수 있어 겹겹이 끼워 넣은 리셋 함수를 피할 수 있다.
Promise의 단점:
  • Promise를 취소할 수 없습니다. 새로 만들면 즉시 실행되며 중도에 취소할 수 없습니다.
  • 리셋 함수를 설정하지 않으면Promise 내부에서 던진 오류가 외부에 반응하지 않습니다
  • pending 상태일 때 현재 어느 단계까지 진전되었는지 알 수 없음
  • 2.기본용법


    ES6에 따르면 Promise 객체는 Promise 인스턴스를 생성하는 데 사용되는 구조 함수입니다.
    const promise = new Promise(function(resolve, reject){
        // ... some code
    
        if ( /*   */ ){
           resolve(value);
        } else {
            reject(value);
        }
    })
    

    resolve의 역할은 Promise 대상의 상태를'미성공'에서'성공'(즉pending에서resolved)으로 바꾸고 비동기 작업이 성공했을 때 호출하며 비동기 작업의 결과를 매개 변수로 전달합니다.
    프로젝트 함수의 역할은 Promise 대상의 상태를 '미완성' 에서 '실패' (즉 pending에서 Rejected) 로 바꾸고, 비동기 작업이 실패할 때 호출하며, 비동기 작업이 보고한 오류를 매개 변수로 전달합니다.
    Promise 실례가 생성된 후, then 방법으로 각각 Resolved 상태와 Rejected 상태의 리셋 함수를 지정할 수 있습니다.
    promise.then(function(value){
        // success
    }, function(){
        // failure
    })
    

    resolve 함수와reject 함수를 호출할 때 인자가 있으면, 인자는 리셋 함수에 전달됩니다.Reject 함수의 매개변수는 일반적으로 Error 객체의 인스턴스이며 플롯 오류를 나타냅니다.resolve 함수의 매개변수는 일반 값 이외에 다른 Promise 인스턴스일 수도 있습니다. 예를 들어,
    const p1 = new Promise(function(resolve, reject){
       // ...
    })
    
    const p2 = new Promise(function(resolve, reject){
      // ...
      resolve(p1)
    })
    

    위 코드에서 p1과 p2는 모두Promise의 실례이지만 p2의resolve 방법은 p1을 매개 변수로 한다. 즉, 하나의 비동기 조작의 결과는 다른 비동기 조작으로 되돌아가는 것이다.
    주의, 이때 p1의 상태는 p2에 전달된다. 즉, p1의 상태가 p2의 상태를 결정한다.만약 p1의 상태가 pending이라면 p2의 리셋 함수는 p1의 상태 변화를 기다릴 것이다.만약 p1의 상태가 이미 Resolved나rejected라면 p2의 리셋 함수는 즉시 실행될 것입니다.
    const p1 = new Promise(function (resolve, reject) {
      setTimeout(() => reject(new Error('fail')), 3000)
    })
    
    const p2 = new Promise(function (resolve, reject) {
      setTimeout(() => resolve(p1), 1000)
    })
    
    p2
      .then(result => console.log(result))
      .catch(error => console.log(error))
    // Error: fail
    

    위에서 p2가 다른 Promise로 되돌아와서 p2의 상태가 무효가 되었고 p1의 상태가 p2의 상태를 결정합니다.
    주의: Resolve나 Reject를 호출해도 Promise의 매개 변수 함수 실행을 끝내지 않습니다
    new Promise( (resolve, reject) => {
        resolve(1);
        console.log(2)
    }).then( r => {
        console.log(r)
    })
    
    // 2
    // 1
    
    new Promise((resolve, reject) => {
      return resolve(1);
      //  
      console.log(2);
    })
    

    3. Promise.prototype.then()


    n 방법은 새로운 Promise 실례를 되돌려줍니다. (주의하십시오. 원래 그 Promise 실례가 아닙니다.) 따라서 체인 쓰기, 즉 then 방법 뒤에 다른 then 방법을 사용할 수 있습니다.
    getJSON("/post/1.json").then(function(post) {
      return getJSON(post.commentURL);
    }).then(function funcA(comments) {
      console.log("resolved: ", comments);
    }, function funcB(err){
      console.log("rejected: ", err);
    });
    

    화살표 함수로 쓰기
    getJSON('/post/1.json').then{
        post => getJSON(post.commentURL)
    }.then(
        comments => console.log("resolved: ", comments),
        err => console.log('rejected: ', err)
    );
    

    4. Promise.prototype.catch()


    Promise.prototype.catch 방법은.오류 발생 시 리셋 함수를 지정하는 데 사용되는 null,rejection 별명
    getJSON('/posts.json').then(function(posts){
       // ...
    }).catch(function(error){
       //  getJSON 
       console.log(' ', error);
    })
    

    다음 예는 다음과 같습니다.
    const promise = new Promise(function(resolve, reject){
       throw new Error('test')
    })
    promise.catch(function(error){
        console.log(error)
    })
    
    // Error: test
    

    위 코드에서promise가 오류를 던지면catch 방법이 지정한 리셋 함수에 포착됩니다
    등가 쓰기:
    // 
    const promise = new Promise(function(resolve, reject){
       try {
          throw new Error('test');
       } catch (e){
          reject(e)
       }
    })
    
    promise.catch(function(error){
       console.log(error)
    })
    
    // 
    const promise = new Promise(function(resolve, reject){
       reject(new Error('test'));
    })
    
    promise.catch(function(error){
       console.log(error)
    })
    
    const promise = new Promise(function(resolve, reject) {
      resolve('ok');
      throw new Error('test');
    });
    promise
      .then(function(value) { console.log(value) })
      .catch(function(error) { console.log(error) });
    // ok
    

    위의 코드에서 Promise는 Resolve 문장 뒤에서 다시 오류를 던지면 잡히지 않고 던지지 않은 것과 같다.프로미스의 상태가 바뀌면 그 상태가 영구적으로 유지되고 더는 변하지 않기 때문이다.
    주의: 일반적으로then 방법에서 Reject 상태의 리셋 함수 (즉 then의 두 번째 인자) 를 정의하지 말고,catch 방법을 항상 사용합니다.
    // bad
    promise
       .then(function(){
          // success
       }, function(){
          // error
       })
    
    
     // good
     promise
        .then(function(data){
            // success
        })
        .catch(function(error){
            // error
        })
    

    전통적인try/catch 코드 블록과 달리catch 방법으로 오류를 수신하지 않으면Promise 대상이 던진 오류는 외부 코드로 전달되지 않고 아무런 반응도 일어나지 않습니다
    이 코드를 보십시오:
    const someAsyncThing = function(){
        return new Promise(function(resolve, reject){
           // , x 
           resolve(x + 2);
        })
    }
    
    someAsyncThing().then(function(){
        console.log('everying is great');
    })
    
    setTimeout( () => console.log(123), 2000)
    

    Promise 내부에서 오류가 발생했지만 123의 실행을 막지 못했습니다

    5. Promise.all()


    여러 개의 Promise 인스턴스를 새로운 Promise 인스턴스로 포장하는 데 사용
    const p = Promise.all([p1,p2,p3])
    

    p1, p2, p3이 모두 성공해야만 p가 성공할 수 있다.
    만약 p1, p2, p3이 자신의catch 방법이 있다면 먼저 자신의catch 방법을 호출할 것이다.

    6. Promise.race()

    const p = Promise.race([p1,p2,p3])
    

    위 코드에서 p1, p2, p3 중 하나의 실례가 먼저 상태를 바꾸면 p의 상태는 따라서 바뀐다.먼저 바뀐 Promise 실례의 반환값은 p의 리셋 함수에 전달됩니다.

    7. Promise.resolve()


    기존 객체를 Promise 객체로 전환
    const jsPromise = Promise.resolve($.ajax('/whatever.json'));
    

    위 코드는 Jquery에서 생성한 deferred 대상을 새로운 Promise 대상으로 변경합니다
    Promise.resolve('foo')
    // 
    new Promise(resolve => resolve('foo'))
    

    8. Promise.reject()


    새 Promise 인스턴스를 반환합니다. 이 인스턴스의 상태는 Rejected입니다.

    9. 두 가지 유용한 방법

  • done(): 리셋 체인의 끝에 있어 발생할 수 있는 모든 오류를 제거합니다.실현 원리:
  • Promise.prototype.done = function(onFulfilled, OnRejected){
       this.then(onFulfilled, OnRejected)
         .catch(function(reason){
             // 
             setTimeout(() => { throw reason }, 0);
         })
    }
    
  • finally()Promise 객체의 마지막 상태와 관계없이 수행되는 작업입니다.

  • 실현 원리
    Promise.prototype.finally = function(callback){
      let p = this.constructor;
      return this.then(
        value  => P.resolve(callback()).then(() => value),
        reason => P.resolve(callback()).then(() => { throw reason })
      );
    }
    

    10. 적용


    그림을 로드하려면 다음과 같이 하십시오.
    const preloadImage = function(path){
      return new Promise(function(resolve, reject){
        const image = new Image();
        image.onload  = resolve;
        image.onerror = reject;
        image.src = path;
      })
    }
    

    좋은 웹페이지 즐겨찾기