Javascript 약속 파악

37488 단어 promisejavascript
약속은 비동기 작업이 최종적으로 완성되었거나 실패했음을 나타내는 대상이다.이것은 단지 우리가 약속으로 비동기 코드를 작성할 수 있다는 것을 의미할 뿐이다. 우리가 리셋 함수를 사용하는 것처럼. 그러나 좀 가볍고 가장 중요한 것은 리셋 지옥의 함정에 빠지지 않는 것이다😉.

무엇이 약속입니까?
promise는 비동기 실행 코드의 구조로 정해진 시간에 다음과 같은 상태 중 하나에 있을 수 있습니다.

  • 미정: - 초기 상태, 만족도 거절도 하지 않습니다.

  • 완료됨: - 성공적으로 실행되어 then 프로세서를 통해 값을 되돌려줍니다.

  • 거부: - 장애가 발생했습니다. catch 프로세서 처리를 사용할 수 있습니다.
  • return new Promise((resolve, reject) => {
      setTimeout(() => resolve("done"), 1000);
    })
    
    위의 코드는 setTimeout를 사용했는데, 이 예에서는 1초 동안의 값인'done'으로 약속을 해석합니다.
    다음promise를 사용하여 GitHub 사용자 정보를 얻는 코드를 고려하십시오.
    
     function fetchUser(username) {
      fetch('https://api.github.com/users/' + username)
      .then(response => response.json())
      .then( data => {
        const str = JSON.stringify(data, undefined, 2);
        document.getElementById('content').innerHTML = str;
      })
      .catch( error => console.error(error));
    }
    
    fetchUser('saroj990');
    
    
    처음에 약속은 본 컴퓨터의javascript에 베이킹되지 않았고(es6는 본 컴퓨터의javascript에 구축될 것임) 제3자 라이브러리(예를 들어 Q,BlueBird를 통해 제공되었다.따라서 그 동안 개발된 모든 라이브러리는 전용 단독 프로미스 라이브러리를 사용하여 비동기성을 실현할 수 있다.

    어떻게 약속을 세웁니까?
    우리는 Promise 수신 resolvereject 을 매개 변수로 삼아 값을 되돌려 주려고 할 때 resolvereject 를 사용하여 오류가 있는 약속을 거부할 수 있는 새로운 실례를 만들 수 있습니다.
    
    function doAsync() {
      return new Promise((resolve, reject) => {
        const number =  Math.ceil(Math.random() * 10);
        if (number % 2 === 0) {
          setTimeout(() => resolve("even"), 2000);
        } else {
          setTimeout(() => reject("odd"), 2000);
        }
      });
    }
    
    
    우리는 1에서 10 사이의 무작위 수를 계산하고 있다.만약 이 숫자가 짝수라면, 우리는 약속을 할 것이다.만약 가치가 홀수라면 우리는 약속을 거절할 것이다.
    다음은 우리가 약속을 어떻게 이행하는가이다.
    doAsync()
      .then((value) => {
        // success handler
      })
      .catch(err => {
        //log error
      });
    
    
    우리가 약속을 해석할 때 then 처리 프로그램은 이 값을 받을 것입니다. 거부하면 오류는 catch 처리 프로그램에 포착됩니다.

    우리는 왜 약속을 해야 합니까?
    하면, 만약, 만약...👌👌. 하지만 나는 여기서 간단명료하게 유지할 것이다. 이렇게 하면 우리는 주제에서 벗어나지 않을 것이다.
    약속의 제기는 지옥의 문제를 완화시키기 위한 것이다.

    지옥으로 돌아가다
    리셋은 매개 변수로 다른 함수에 전달될 수 있는 함수일 뿐이며, 더 많은 리셋이 다른 함수에 끼워져 있을 때 코드는 이해하기 어려워진다.
    function getUser(id, profile, callback) {
      User.find(id, function (err, user) {
        if(err) {
          callback(err);
        } else {
          user.profile = profile;
          user.save(function(err, user) {
            if(err) { 
              callback(err)
            } else {
              Subscription.findSubscription(id, function(err, subscription) {
                if(err) {
                  callback(err) ;
                } else {
                  user.subscription = subscription;
                  callback(subscription);
                }
              });
            }
          });
        }
      });
    }
    
    위의 코드는 보기에 매우 엉망이고 표현력이 전혀 없으며, 다른 플러그인 레벨이 나타날 때 상황은 더욱 나빠질 것이다.
    약속으로 같은 코드를 다시 생각해 봅시다.
    function getUser(id, profile) {
      const currentUser = {};
      return new Promise((resolve, reject) => {
        User
          .find(id)
          .then((user) => {
            currentUser = user;
            currentUser.profile = profile })
          .then(() => Subscription.find(id))
          .then(subscription => {
            currentUser.subscription = subscription;
            return resolve(currentUser)
          })
          .catch(err => reject(err))
      })
    
    }
    
    지금 코드가 굉장히 깔끔해 보여요.👌👌. 안 그래?따라서 약속을 사용하는 것은 코드를 더 쉽게 읽을 수 있고 이해하기 쉽기 때문에 추가적인 장점이 있습니다.

    약속을 묶다
    약속 체인은 하나의 약속의 출력이 다른 약속의 입력이 되는 모델이다.
    다음은 우리가 예약을 시도한 예이다.
    
    Appointment
    .findSlot(time)
    .then(slot => BookAnAppointment(slot.id))
    .then(appointment => FinishPayment(appointment.id))
    .then(payment => getInvoice(payment.id))
    .then(invoice => console.log(invoice))
    .catch(err => console.log(err));
    

    평행 집행
    어떤 경우 약속은 다른 약속과 무관하게 독립적으로 집행해야 한다.Promise.allpromise에는 Javascript구조가 있는데 이를 실현하기 위해 약속을 병행한다.
    // marks a user in-active
    function markInActive(id) {
      return User
      .findById(id)
      .then(user => {
        user.active = false;
        //returns a promise
        return user.save();
      });
    }
    
    // collect the promises into an array
    const promises = []
    for (let i=0; i < ids.length; i++) {
      promises.push(markInActive(ids[i]));
    }
    
    //execute them altogether
    Promise.all(promises)
    .then(result => console.log(result))
    .catch(error => console.log(error));
    
    
    약속과 병행 실행을 연결하는 것이 어떤 차이가 있는지 알고 싶을 수도 있다.그래, 우리 하나의 예로 평가해 보자.
    
    function promiseOne() {
      return new Promise((resolve, reject) => {
        setTimeout(() => resolve('promiseOne'), 1000);
      })
    }
    
    function promiseTwo() {
      return new Promise((resolve, reject) => {
        setTimeout(() => resolve('promiseTwo'), 1000);
      })
    }
    
    function promiseThree() {
      return new Promise((resolve, reject) => {
        setTimeout(() => resolve('promiseThree'), 1000);
      })
    }
    
    약속이 체인에서 실행될 때 두 번째 약속은 첫 번째 약속이 완성될 때만 실행된다.
    promiseOne()
    .then((res1) => { 
      console.log(res1);
      return promiseTwo() 
    })
    .then((res2) => {
      console.log(res2);
      return promiseThree();
    }).then(res3 => {
      console.log(res3);
    })
    .catch(err => console.log(err));
    
    /*
    output
    promiseOne
    promiseTwo
    promiseThree
    each promise takes 1sec to execute
    effective time: 3sec
    */
    
    현재, 우리는 Promise.all를 사용하여 같은 코드를 시도하고, 모든 약속을 동시에 실행할 수 있도록 병행 실행을 허용합니다.
    
    Promise.all([ promiseOne(), promiseTwo(), promiseThree()])
      .then(result => console.log(result))
      .catch(err => console.log(err));
    
    
    /*
    output: 
    [ 'promiseOne', 'promiseTwo', 'promiseThree' ]
    all the promises get executed at the same time
    so effective time: 1sec
    */
    

    콜백을 약속으로 바꾸다
    만약 당신이 이 점을 계속 따르고 있다면, 리셋을 약속으로 바꾸는 방법을 알아야 합니다.우선, 우리는 왜 우리가 약속을 되돌려야 하는지 알아야 한다.
    일부 라이브러리 함수에promise variant 방법이 없을 때가 있습니다. (현재 거의 모든 라이브러리에promise 인터페이스 방법이 제공될 것 같습니다.) 그러나 약속으로 사용하기를 원합니다.
    function saveUser(payload) {
      return new Promise((resolve, reject) => {
        User.save(payload, function(err, user) {
          if(err) return reject(err);
          return resolve(user);
        });
      });
    }
    
    User 모델save 방법은 리셋 방법입니다. 우리는 그것을 새로운 Promise 구조에 포장했을 뿐입니다. 리소스와reject가 포함되어 있습니다.오류가 발생하면 약속을 잘못 거절합니다. 그렇지 않으면 사용자 정보로만 해결할 것입니다.

    오류 처리 (캡처/최종)
    약속을 만드는 것은 흥미롭지만, 약속을 실행할 때 발생할 수 있는 오류를 처리하지 않으면 아무 소용이 없습니다.이를 실현하기 위해서, 우리는 catch 처리 프로그램을 사용할 수 있으며, 오류 대상을 처리 프로그램 함수의 매개 변수로 수신할 수 있다.
    다음은catch 블록으로 처리된 오류 예시 코드입니다.
    new Promise((resolve, reject) => {
      reject("some error happened!");
    }).catch(err => console.log(err));
    
    
    우리도 약속에서 명확한 잘못을 던질 수 있다. 그것은 위와 완전히 같다.
    new Promise((resolve, reject) => {
      throw new Error("some error occurred!!")
    }).catch(err => console.log(err));
    
    catch 프로세서는 프로그램 내에서 발생하는 동기화나 비동기화 이벤트를 처리할 수 있습니다.
    우리는 위의 예에서 우리가 고의로 잘못을 제기한 것을 보았다.이제 또 다른 잘못이 비동기적인 예임을 살펴봅시다.
    const prom1 = () => new Promise((resolve, reject) =>  {
      setTimeout(() => {
        //rejects after 2sec
        return reject("rejected prom1 promise");
      }, 2000)
    });
    
    new Promise((resolve, reject) => resolve("done"))
      .then(res => prom1())
      .catch(err => console.log(err))
    
    여기서 첫 번째 방법prom1은 비동기적으로 약속을 거부한다(setTimeout만 모방했을 뿐)😉).thencatch 블록은 아래와 같이 하나씩 끼워 넣을 수 있다.
    
    new Promise((resolve, reject) => {
      resolve("done")
    }).then(res => {
      console.log("response is : ", res);
      throw new Error("error after the first promise resolved");  // synchronous error
    }).catch(err => {
      console.log("error caught in catch handler", err);
      return "You can rest now"; 
    //simply pass the value to next level
    }).then(res => console.log(res))
    .catch(err => console.log(err)); 
    // prints "you can rest now"
    
    
    
    일반적으로, 사람들은 약속의 끝에 추가된catch 블록만 사용하는데, 발생하는 모든 오류는catch 처리 프로그램에 의해 포착된다.

    마침내
    약속의 또 다른 중요한 부분은 finally 블록으로 약속이 성공하든 거절당하든 간에 모두 집행된다.
    
    new Promise((resolve, reject) => resolve("done"))
    .then(res => console.log(res))
    .catch(err => console.log("I can catch fish too. :)"))
    .finally(() => console.log("I am inevitable, I will always get a chance to execute"))
    
    
    하나의 예로 더 잘 설명해 드리겠습니다. 그러면 우리는 finally 블록의 배후 원인을 진정으로 이해할 수 있습니다.
    isLoading = true;
    fetchUser(id)
    .then(user => subscribeToNewsLetter(user.id))
    .then(response => {
      console.log("subscribed to news letter", response);
      // set loader to false once the user info is retrieved
      isLoading = false;
    })
    .catch(err => { 
      console.log(err);
      // in case of error
      isLoading = false;
    });
    
    
    우리는 isLoading 변수를 사용하여 비동기 작업이 언제 시작되고, 언제 완성되는지 추적합니다. 그러면 응답을 받을 때 불러오는 프로그램을 표시하고 숨길 수 있습니다.
    말할 것도 없이 우리는 두 개의 다른 곳에서isLoadingfalse로 설정했다.
  • 성공 처리기then
  • 오류 처리 프로그램 중입니다.만약 어떤 오류가 발생한다면, 우리는 프로그램을 영원히 불러오기를 원하지 않기 때문이다.너.. 그래?😂😂
  • 이런 실현은 효과적이지만 효율이 높지 않을 뿐만 아니라 중복된 것이다.우리는 finally 블록으로 그것을 더욱 잘 처리할 수 있다.
    isLoading = true;
    fetchUser(id)
    .then(user => subscribeToNewsLetter(user.id))
    .then(response => console.log("subscribed to news letter", response))
    .catch(err => console.log(err))
    .finally(() => isLoading = false);
    
    
    Finally 블록은 실행될 것입니다. 약속한 대로 무슨 일이 발생하든지 간에 이것은 한 장소로서 정리와 닫기DB, socket 연결 등을 할 수 있습니다.
    만약 네가 이미 이 점을 보충했다면, 축하해!!😁👍. 만약 이 글이 자바스크립트의 약속을 이해하는 데 도움이 된다고 생각한다면 망설이지 말고 이 글을 좋아해서 당신의 사랑을 표현하세요.
    만약 글 중 일부 부분이 개선될 수 있다고 생각한다면, 평론을 추가하세요.고맙겠습니다.

    좋은 웹페이지 즐겨찾기