[Promise] 알 고 있 습 니 다.

43152 단어 웹 전단
제목https://github.com/nswbmw/node-in-debugging/blob/master/3.1 Promise.md
선명 하고 우아 한 코드 를 어떻게 쓰 느 냐 도 디 버 깅 의 중요 한 부분 이다. 과거 오 랜 시간 동안 자 바스 크 립 트 가 가장 토로 하 는 것 은 지옥 (callback hell) 으로 돌아 가 는 것 이다.코드 먼저 보기:
이제 10 문제 로 앞서 배 운 Promise 의 지식 포 인 트 를 공 고 히 하 겠 습 니 다.
제목 1: Promise 구조 함수
const promise = new Promise((resolve, reject) => {
  console.log(1)
  resolve()
  console.log(2)
})
promise.then(() => {
  console.log(3)
})
console.log(4)

실행 결과:
1
2
4
3

설명: Promise 구조 함 수 는 동기 적 으로 실 행 됩 니 다. promise. then 의 함 수 는 비동기 적 으로 실 행 됩 니 다.
제목 2: Promise 상태 기
const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('success')
  }, 1000)
})
const promise2 = promise1.then(() => {
  throw new Error('error!!!')
})

console.log('promise1', promise1)
console.log('promise2', promise2)

setTimeout(() => {
  console.log('promise1', promise1)
  console.log('promise2', promise2)
}, 2000)

실행 결과:
promise1 Promise {  }
promise2 Promise {  }
(node:50928) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: error!!!
(node:50928) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
promise1 Promise { 'success' }
promise2 Promise {
   Error: error!!!
    at promise.then (...)
    at  }

설명: promise 는 3 가지 상태 가 있 습 니 다: pending, fulfilled 또는 rejected.상태 변 화 는 pending - > fulfilled 또는 pending - > rejected 일 수 있 으 며, 상태 가 바 뀌 면 다시 변 할 수 없습니다.위의 promise 2 는 promise 1 이 아니 라 돌아 오 는 새로운 Promise 인 스 턴 스 입 니 다.
제목 3: Promise 상태의 변경 불가
const promise = new Promise((resolve, reject) => {
  resolve('success1')
  reject('error')
  resolve('success2')
})

promise
  .then((res) => {
    console.log('then: ', res)
  })
  .catch((err) => {
    console.log('catch: ', err)
  })

실행 결과:
then: success1

설명: 구조 함수 중의 resolve 나 reject 는 첫 번 째 실행 시 에 만 유효 하 며, 여러 번 호출 하 는 것 은 아무런 역할 이 없 으 며, 코드 2 의 결론 을 다시 한 번 입증 합 니 다: promise 상태 가 바 뀌 면 다시 바 꿀 수 없습니다.
두 가지 예 를 다시 보 자.
const promise = new Promise((resolve, reject) => {
  console.log(1)
  return Promise.reject(new Error('haha'))
})
promise.then((res) => {
  console.log(2, res)
}).catch((err) => {
  console.error(3, err)
})
console.log(4)
console.log(promise)

실행 결과:
1
4
Promise {  }
(node:22493) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: haha
(node:22493) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
const promise = new Promise((resolve, reject) => {
  console.log(1)
  throw new Error('haha')
})
promise.then((res) => {
  console.log(2, res)
}).catch((err) => {
  console.error(3, err)
})
console.log(4)
console.log(promise)

실행 결과:
1
4
Promise {
   Error: haha
    at Promise (/Users/nswbmw/Desktop/test/app.js:6:9)
    ...
3 Error: haha
    at Promise (/Users/nswbmw/Desktop/test/app.js:6:9)
    ...

설명: 구조 함수 에 서 는 resolve (pending - > fullfiled) 또는 reject (pending - > rejected) 또는 throw 하나의 error (pending - > rejected) 를 호출 하여 상 태 를 바 꿀 수 있 습 니 다.그래서 첫 번 째 예 의 promise 상 태 는 pending 이 고 'then / catch' 를 호출 하지 않 습 니 다.
제목 4: Promise 체인 호출
Promise.resolve(1)
  .then((res) => {
    console.log(res)
    return 2
  })
  .catch((err) => {
    return 3
  })
  .then((res) => {
    console.log(res)
  })

실행 결과:
1
2

설명: promise 는 체인 으로 호출 할 수 있 습 니 다.체인 호출 을 꺼 내 면 우 리 는 보통 return this 를 통 해 이 루어 질 것 이 라 고 생각 하지만 Promise 는 이렇게 이 루어 지지 않 습 니 다.promise 는. then 이나. catch 를 호출 할 때마다 새로운 promise 를 되 돌려 주 고 체인 호출 을 실현 할 수 있 습 니 다.
Axios 는 체인 호출 을 통 해 차단 기 를 실현 하 는 것 이다.원 리 는 다음 과 같다.
/**         ,    promiseRequest */
let requestPromise = function () {
  let chain = [{
    resolved: () => { console.log('xhr'); return 'xhr'},
    rejected: () => 'rejected'
  }]

  let requestInters = ['request1', 'request2', 'request3']
  requestInters.forEach(request => {
    chain.unshift({
      resolved: () => { console.log(request); return request},
      rejected: () => `${err}${request}`
    })
  })

  let responseInters = ['response1', 'response2', 'response3']
  responseInters.forEach(response => {
    chain.push({
      resolved: () => { console.log(response); return response},
      rejected: () => `${err}${response}`
    })
  })

  let promise = Promise.resolve('config')

  while (chain.length) {
    let { resolved, rejected } = chain.shift()
    //        

    promise = promise.then(resolved, rejected)
  }
  // return promise   
  // promise.then(resolved1, rejected1).then(resolved2, rejected2).then(resolved2, rejected3).then() ....
  return promise
}

requestPromise().then(res => {

  console.log(res)
  // request3
  // request2
  // request1
  // xhr
  // response1
  // response2
  // response3
  // response3
})

제목 5: Promise 내부 상태
const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    console.log('once')
    resolve('success')
  }, 1000)
})

const start = Date.now()
promise.then((res) => {
  console.log(res, Date.now() - start)
})
promise.then((res) => {
  console.log(res, Date.now() - start)
})

실행 결과:
once
success 1005
success 1007

설명: promise 의. then 또는. catch 는 여러 번 호출 될 수 있 지만, 여기 Promise 구조 함 수 는 한 번 만 실 행 됩 니 다.또는 promise 내부 상태 가 바 뀌 고 값 이 있 으 면 나중에 호출 할 때마다. then 또는. catch 에서 이 값 을 직접 받 습 니 다.
이것 은 우리 의 평소 promise 캐 시 에서 매우 유용 합 니 다. 예 를 들 어 app 이 시 작 될 때 promise 를 잠시 저장 할 수 있 습 니 다. 되 돌아 오지 않 을 때 promise 를 다른 호출 자 에 게 직접 주 는 것 이 아니 라 호출 할 때마다 new promise 로 가 는 것 입 니 다.
제목 6: Promise 오류 의 정상 던 지기
Promise.resolve()
  .then(() => {
    return new Error('error!!!')
  })
  .then((res) => {
    console.log('then: ', res)
  })
  .catch((err) => {
    console.log('catch: ', err)
  })

실행 결과:
then: Error: error!!!
    at Promise.resolve.then (...)
    at ...

설명:. then 또는. catch 에서 return error 대상 은 오 류 를 던 지지 않 기 때문에 후속 적 인. catch 에 포착 되 지 않 습 니 다. 다음 중 하나 로 변경 해 야 합 니 다.
  • return Promise.reject(new Error(‘error!!!’))
  • throw new Error(‘error!!!’)

  • 임의의 비 promise 값 을 되 돌려 주면 promise 대상, 즉 return new Error('error!!!') 등가 return Promise.resolve(new Error('error!!!')) 로 감 싸 지기 때문이다.
    제목 7: Promise 순환 조심
    const promise = Promise.resolve()
      .then(() => {
        return promise
      })
    promise.catch(console.error)
    

    실행 결과:
    TypeError: Chaining cycle detected for promise #
        at 
        at process._tickCallback (internal/process/next_tick.js:188:7)
        at Function.Module.runMain (module.js:667:11)
        at startup (bootstrap_node.js:187:16)
        at bootstrap_node.js:607:3
    

    설명:. then 또는. catch 가 되 돌아 오 는 값 은 promise 자체 일 수 없습니다. 그렇지 않 으 면 순환 을 일 으 킬 수 있 습 니 다.다음 과 유사:
    process.nextTick(function tick () {
      console.log('tick')
      process.nextTick(tick)
    })
    

    제목 8: Promise 값 관통 력
    Promise.resolve(1)
      .then(2)
      .then(Promise.resolve(3))
      .then(console.log)
    

    실행 결과:
    1
    

    설명:. then 또는. catch 의 매개 변 수 는 함수 이 고 비 함수 에 들 어가 면 값 관통 이 발생 합 니 다.
    제목 9: Promise 오류 캡 처
    Promise.resolve()
      .then(function success (res) {
        throw new Error('error')
      }, function fail1 (e) {
        console.error('fail1: ', e)
      })
      .catch(function fail2 (e) {
        console.error('fail2: ', e)
      })
    

    실행 결과:
    fail2: Error: error
        at success (...)
        at ...
    

    설명:. then 은 두 개의 인 자 를 받 을 수 있 습 니 다. 첫 번 째 는 성공 적 인 함수 이 고 두 번 째 는 오 류 를 처리 하 는 함수 입 니 다.catch 는. then 두 번 째 매개 변수의 간편 한 쓰기 입 니 다. 그러나 용법 에 있어 서 주의해 야 할 것 이 있 습 니 다. then 의 두 번 째 처리 오류 함수 (fail 1) 는 첫 번 째 처리 성공 함수 (success) 가 던 진 오 류 를 포착 하지 못 하고 후속 적 인. catch 방법 (fail 2) 은 이전의 오 류 를 포착 할 수 있 습 니 다.물론 다음 코드 도 가능 합 니 다.
    Promise.resolve()
      .then(function success1 (res) {
        throw new Error('error')
      }, function fail1 (e) {
        console.error('fail1: ', e)
      })
      .then(function success2 (res) {
      }, function fail2 (e) {
        console.error('fail2: ', e)
      })
    

    제목 10: Promise 와 이벤트 순환
    Promise.resolve()
      .then(() => {
        console.log('then')
      })
    process.nextTick(() => {
      console.log('nextTick')
    })
    setImmediate(() => {
      console.log('setImmediate')
    })
    console.log('end')
    

    실행 결과:
    end
    nextTick
    then
    setImmediate
    

    설명: process.nextTickpromise.then 는 모두 microtask (그러나 process. nextTick 의 우선 순 위 는 promise. then 보다 크다) 에 속 하고 setImmediate 는 macrotask 에 속 하 며 이벤트 순환 의 check 단계 에서 실 행 됩 니 다.이벤트 순환 의 모든 단계 (macrotask) 간 에 microtask 를 실행 합 니 다. 상기 코드 자체 (macrotask) 는 실행 이 끝 난 후에 microtask 를 한 번 실행 합 니 다.

    좋은 웹페이지 즐겨찾기