build your promise step by step

10301 단어 자바 scriptpromise
최근 Promise 내부 실현 원리 에 관 한 글 을 봤 다.저 자 는 간단명료 한 예 에서 착안 하여 한 걸음 한 걸음 건장 한 구축 Promise 을 실현 했다.나 는 작가 글 의 코드 인 스 턴 스 를 가지 고 문장의 핵심 내용 을 정리 할 것 이다.
여러분 은 분명히 깊이 있 는 반전 함 수 를 본 적 이 있 을 것 입 니 다. 그러면 어떻게 코드 절 차 를 확보 해 야 이 세로 로 포 함 된 코드 를 수평 으로 평평 하 게 만 들 수 있 습 니까?
    doSomething(function(value) {
        console.log('Got a value:' + value);
    })

to this
    doSomething().then(function(value) {
        console.log('Got a value:' + value);
    })

그러면 우 리 는 doSomething 함 수 를 정의 할 때 해당 하 는 변 화 를 해 야 한다.
    function doSomething(callback) {
        var value = 42;
        callback(value);
    }

to this
    function doSomething() {
        return {
            then: function(callback) {
                var value = 42;
                callback(42);
            }
        }
    }

Defining the Promise type
먼저 간단 한 Promise 구조 함 수 를 정의 하 는 코드 를 살 펴 보 겠 습 니 다.
    function Promise(fn) {
        var callback = null;
        this.then = function(cb) {
            callback = cb;
        }
        
        function resolve(value) {
            callback(value)
        }
        
        fn(resolve);
    }

그리고 다시 쓰기 doSomething() 함수:
    function doSomething() {
        return new Promise(function(resolve) {
            var value = 42;
            resolve(value);
        })
    }

다시 정 의 된 doSomething() 함수 가 실 행 된 후에 되 돌아 와 서 하나의 promise 를 얻 을 수 있 습 니 다. 인 스 턴 스 에 then() 방법 이 있 고 리 셋 함 수 를 받 아들 일 수 있 습 니 다.
    doSomething().then(function(value) {
        console.log(value);
    })

그러나 위의 코드 가 잘못 보 고 될 수 있 습 니 다 (callback is undefined). resolve 의 callback 은 then () 방법 중의 callback 의 할당 보다 빠 르 기 때 문 입 니 다.
그러면 Promise 구조 함수 에 대해 조금 만 처리 하고 동기 화 된 코드 setTimeout 를 사용 하여 hack 에서 코드 의 집행 순 서 를 바 꾸 어 resolve 함수 중의 callbackvalue 를 처리 하기 전에 할당 합 니 다.
    function Promise(fn) {
        var callback = null;
        this.then = function(cb) {
            callback = cb;
        }
        
        function resolve(value) {
            setTimeout(function() {
                callback(value);
            }, 1)
        }
        fn(resolve);
    }

여기 서 setTimeout 비동기 함 수 를 통 해 코드 실행 순 서 를 바 꾸 었 고 callback 호출 되 기 전에 할당 되 었 는 지 확인 합 니 다 cb.
다시 호출:
    doSomething().then(function(value) {
        console.log(value);
    })
    // 42
    //    。

그러나 정의 Promise 구조 함수 의 코드 에 문제 가 있 습 니 다. 호출 then() 방법 만 있 으 면 내부 callback 는 여전히 null 이기 때 문 입 니 다.마찬가지 로 정상적으로 집행 할 수 없다.
서 두 르 지 말고 천천히 해라.
Promises have state
사실 Promise 은 상태 가 있다.
  • pending
  • resolved
  • rejected
  • pending => resolved 또는 pending => rejected.상태 가 일단 바 뀌 면 거 스 를 수 없다.다음은 Promise 의 구조 함수 에 state 를 넣 고 state 를 사용 하여 전체 코드 절 차 를 제어 합 니 다.
        function Promise(fn) {
            var state = 'pending', 
                value, 
                deferred;
            
            function resolve(newValue) {
                state = 'resolved';
                value = newValue;
                
                if(deferred) {
                    handle(deferred);
                }
            }
            
            function handle(onResolved) {
                if(state === 'pending') {
                    deferred = onResolved;
                    return ;
                }
                
                onResolved(value);
            }
            
            this.then = function(onResolved) {
                handle(onResolved);
            }
            
            fn(resolve);
        }

    코드 가 이전 보다 더 복잡 해 졌 습 니 다.하지만 지금 은 코드 의 절 차 를 제어 하기 위해 state 를 사용 하고 있다.then() resolve() 는 통제 권 을 새로운 방법 handle() 에 맡 겼 고 handle() 방법 으로 state 의 값 에 따라 절 차 를 진행 했다.
  • 만약 statepending 상태 라면 resolve() 이전에 then() 방법 을 호출 하면 onResolved 리 셋 할당 값 을 하나 deferred 주 고 deferred 이 리 셋 을 저장 합 니 다. 잠시 후 resolve() 호출 할 때 pending 상태 가 resolved 로 바 뀌 고 호출 deferred 합 니 다.
  • then() 방법 전에 resolve() 방법 을 호출 하면 pending 상태 가 resolved 로 바 뀌 고 then() 에 주 입 된 반전 onResolved 을 호출 합 니 다.
  • 이상 의 코드 를 통 해 promise 임 의 횟수 로 호출 할 수 있 습 니 다 then() 방법:
        var promise = doSomething();
        
        promise.then(function(value) {
            console.log('Got a value:', value);
        });
        // 42
        
        promise.then(function(value) {
            console.log('Got the some value again:', value); 
        });
        //42

    그러나 이러한 Promis e 구조 함수 에 문제 가 있 습 니 다. 여러분 은 resolve() 방법 을 호출 하기 전에 여러 번 then() 방법 을 호출 했다 고 상상 할 수 있 습 니 다. 그러면 마지막 then() 방법 에 주입 한 callback 만 유용 합 니 다.이 문 제 를 해결 하 는 방법 은 하나의 deferreds 를 유지 하고 매번 then() 방법 으로 주입 하 는 반전 함 수 를 저장 하 는 것 이다.
    Chaining Promises
    다음 코드 는 가장 일반적인 promise 체인 호출 입 니 다.
        getSomeData()
        .then(filterTheData)
        .then(processTheData)
        .then(displayTheData)
    getSomeData() 방법 을 호출 한 후에 하나 promise 를 되 돌려 줍 니 다. 그러면 then() 방법 을 호출 할 수 있 습 니 다. 마찬가지 로 이 첫 번 째 then() 방법 을 호출 한 후에 도 하나의 promise 대상 을 되 돌려 줍 니 다.이렇게 해야만 계속 then() 방법 을 호출 할 수 있다.
    then () 방법 은 항상 promise 를 되 돌려 줍 니 다.
    다음은 코드 에서 이 루어 집 니 다.
        function Promise(fn) {
            var state = 'pending',
                value,
                deferred = null;
                
            function resolve(newValue) {
                state = 'resolved';
                value = newValue;
                
                if(deferred) {
                    handle(deferred);
                }
            }
            
            function handle(handler) {
                if(state == 'pending') {
                    deferred = handler;
                    return;
                }
                
                if(!handler.onResolved) {
                    handler.resolve(value);
                    return;
                }
                
                var ret = handler.onResolved(value);
                handler.resolve(ret);
            }
            
            this.then = function(onResolved) {
                return new Promise(function(resolve) {
                    handle({
                        onResolved: onResolved,
                        resolve: resolve
                    });
                });
            };
            
            fn(resolve);
        }

    이번 코드 에서 호출 then() 방법 을 사용 하면 새로운 생 성 promise 을 되 돌려 줍 니 다.그것 은 then() 방법 을 가지 고 있 으 며, 계속 호출 then() 할 수 있 으 며, 새로 생 성 된 promise 대상 을 되 돌려 줄 수 있다.이렇게 계속 진행 하 다.이것 은 Promise 체인 호출 을 실현 했다.
    구체 적 인 코드 실현 을 살 펴 보 자. resolve() 방법 은 변 함 이 없 지만 handle() 방법 은 하나의 handler 대상 을 받는다.handler 대상 은 2 개의 속성 이 있 는데 하 나 는 onResolved 이 고 then() 방법 에 주 입 된 반전 함수 로 전 달 된 이전 promise 이 전달 한 값 을 처리 합 니 다.다른 하 나 는 resolve, Promise 구조 함수 내부 정의 resolve() 방법 으로 Promise 상태 와 value 값 을 바 꾸 는 데 사용 된다.
    구체 적 으로 분석 해 보면 handle() 함수:
        function handle(handler) {
            if(state === 'pending') {
                deferred = handler;
                return;
            }
            
            if(!handler.onResolved) {
                handler.resolve(value);
                return;
            }
            
            var ret = handler.onResolved(value);
            handler.resolve(ret);
        }

    매번 호출 then() 방법 으로 하나의 promise 대상 을 새로 만 드 는 과정 에서 handle({onResolved: onResolved, resolve: resolve}) 에서 resolve 속성 은 항상 정 의 된 과정 에서 외부 resolve 방법 에 대한 인용 이다.즉, 지난번 promise 에서 정 의 된 resolve.
    then () 방법 에 반전 함 수 를 주입 할 때 onResolved 방법 을 호출 하고 반환 값 ret 를 얻 으 며 resolve 방법 을 입력 하여 state 의 값 을 바 꾸 고 promise 에서 계속 전달 해 야 할 값 을 변경 합 니 다.onResolved 방법 에서 처 리 된 값 을 되 돌려 줍 니 다. 다음 promise 는 이 값 을 받 을 수 있 습 니 다. onResolved 가 되 돌아 오지 않 으 면 다음 promise 에 들 어 가 는 것 은 undefined * 입 니 다.
        doSomething().then(function(result) {
            console.log('First result', result);
            return 88;
        }).then(function(secondResult) {
            console.log('second result', secondResult);
        })
        
        //the output is 
        //
        //First result 42
        //Second result 88
        
        doSomething().then(function(result) {
            console.log('First result', result);
        }).then(function(secondResult) {
            console.log('Second result', secondResult);
        })
        
        //now the output is
        
        //First result 42
        //Second result undefined
        
     then()         ,     resolve  ,  state  ,       promise      ,         promise。
    
        doSomething().then().then(function(result) {
            console.log('Got a result', result);
        });
        
        //the output is 
        //
        //Got a result 42

    주로 handle() 방법 에서 호출 resolve 방법 으로 이전 promise 에서 얻 은 value 과 다음 promise 으로 들 어 온 value 을 얻 었 기 때문이다.
        if(!handler.onResolved) {
            handler.resolve(value);
            return;
        }
         then()           pending   promise,   resolve      ,  then()          ,     ,            ,          ,resolve        promise      ,        promise  。 then()             。
    

    다시 한 번 Promise 에 대한 강 화 를 통 해 promise 의 기능 을 완성 했다.
    reject 부분 에 대해 서 는 이틀 이 지나 면

    좋은 웹페이지 즐겨찾기