Promise 체인 호출 분석

7540 단어

Promise 체인 호출 분석


Promise가 무엇을 하는지 나는 군더더기 없이 설명할 것이다. 네가 이 글을 보았을 때, 나도 네가 Promise를 사용한 것을 묵인했다
먼저 예를 들다
//  id
function getUserId() {
    return new Promise(function(resolve, reject) {
      setTimeout(function() {
        resolve(186)
      }, 1e3)
    })
}
//  id 
function getMobileByUserId(userId) {
    return new Promise(function(resolve, reject) {
        setTimeout(function(){
            resolve(userId + '****5836')
        }, 1e3)
    })
}

두 가지 방법, getUserId(약칭 IDfun)와 getMobileByUserId(약칭 MOfun)는 둘 다return에서 하나의 Promise 실례를 얻었다. 전자는 사용자 id를 얻고 후자는 사용자 id를 가지고 핸드폰 번호를 바꾸는 것이다. MOfun의 출력은 IDfun의 출력에 의존한다. 이렇게 하면 두 가지 다른 동작은 질서정연한 실행을 보장해야 한다.
여기에 대응하는 해결 방법이 있을 것이다. 나는 여기에 예시를 하나 열거했다.
IDfun()
    .then(MOfun)
    .then(function(res) {
        console.log(res)
    })

우선, IDfun을 호출하여 그 Promise 실례의 then 방법에서 MOfun을 전송했고 그 뒤에 또한then 방법이다. 그 안에 하나의callback 함수가 전송되었다. 이때 callback 함수에서 출력된 값은 무엇이고 왜일까. 일반적인 상황에서 then 방법에서 전송된 것은 하나의callback인데 이 예에서 전송된 것은 Promise를 포함하는 함수이다.내부적으로 사용자의 id를 MOfun에 전달하고 출력하는 방법
이렇게 말하면, 나는 먼저 몇 가지 Promise 중의 몇 가지 비교적 핵심적인 방법을 열거한다.
// this Promise 
//  
this.then = function (onFulfilled) {
    return new Promise(function (resolve) {
        handle({
            onFulfilled: onFulfilled || null,
            resolve: resolve
        });
    });
};

function handle(deferred) {
    if (state === 'pending') {
        deferreds.push(deferred);
        return;
    }

    var ret = deferred.onFulfilled(value);
    deferred.resolve(ret);
}
//  state value , 
function resolve(newValue) {
    if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
        var then = newValue.then;
        if (typeof then === 'function') {
            then.call(newValue, resolve);
            return;
        }
    }
    state = 'fulfilled';
    value = newValue;     // value 
    setTimeout(function () {
        deferreds.forEach(function (deferred) {
            handle(deferred);
        });
    }, 0);
}

이 몇 가지 방법을 참조하여 우리는 다시 아까 그 예로 돌아간다.
  • 1.IDfun을 실행하면 Promise 인스턴스(IDPro)를 반환하고 IDPro의 코드를 실행합니다. 이때 비동기적으로 요청을 보내고 then 방법을 계속 실행하면 then 방법에 MOfun
  • 이 전송됩니다.
  • 2.then 방법에 들어가면 Promise 실례(BridgePro1)를 되돌려주고 handle 방법handle({
    onFulfilled: onFulfilled || null,  //  onFulfilled === MOfun
    resolve: resolve  // resolve BridgePro1 resolve
    }를 호출합니다.
  • 3.handle에 들어가면 IDPro의 then 방법이 먼저 실행되고 resolve가 실행됩니다. 이때 state ===pending, 이 때 전송된 대상push를 IDPro의 deferreds 그룹에 되돌려줍니다.
  • 4.IDPro에서 비동기식 작업이 완료되고 resolve를 실행하며 id로 전송186
  • 5.resolve 방법에 들어갔을 때 newValue가 if조건을 충족시키지 못하면 건너뛰고 계속 아래로 실행합니다. state===>fulfilled,value===>186,setTimeout은 0입니다. 이 코드를 실행할 때 then 방법이 실행되었음을 보증합니다. IDPro의 deferreds 수조를 순환하여 수조의 모든 항목을handle에 전송하고 실행합니다
  • function resolve(newValue) {   // newValue === 186
            if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
                var then = newValue.then;
                if (typeof then === 'function') {
                    then.call(newValue, resolve);
                    return;
                }
            }
            state = 'fulfilled';
            value = newValue;     // value 
            setTimeout(function () {
                // deferreds then 
                // [{
                //    onFulfilled: MOfun,
                //    resolve: resolve
                // }]
                deferreds.forEach(function (deferred) {  
                    handle(deferred);
                });
            }, 0);
        }
  • 6.handle에 들어갑니다. 이 때state====fulfilled, deferred의 onFulfilled(MOfun)를 실행하고value를 전송하고,Promise 실례(MOPro)를 되돌려줍니다. 이 때ret====MOPro, deferred의resolve(BridgePro1의 resolve)를 계속 실행하고ret
  • 를 전송합니다.
      // state === fulfilled
        // deferred ===> 
        //  {
        //    onFulfilled: MOfun,
        //    resolve: resolve
        //  }
        function handle(deferred) {
            if (state === 'pending') {
                deferreds.push(deferred);
                return;
            }
        
            var ret = deferred.onFulfilled(value);  // value === 186
            deferred.resolve(ret);
        }
  • 7.resolve에 들어가면 newValue가 판단 조건을 충족합니다
  •     function resolve(newValue) {   // newValue === MOPro
            if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
                // then  MOPro then
                var then = newValue.then;
                if (typeof then === 'function') {
                    //  then , this MOPro, resolve, resolve BridgePro1 resolve, 
                    then.call(newValue, resolve);
                    return;
                }
            }
            state = 'fulfilled';
            value = newValue;     
            setTimeout(function () {
                deferreds.forEach(function (deferred) {  
                    handle(deferred);
                });
            }, 0);
        }
  • 8.OPro의 then 방법에 들어가서handle를 호출하여 대상을 전송합니다. 이때 MOPro의 deferreds 수조에 두 가지가 있습니다. 하나는 위에서 Resolve를 통해 전송된 것이고 다른 하나는 전송된 콜백 함수
  • 입니다.
    // ===> callback
        function(res) {
            console.log(res)
        }
    
        this.then = function (onFulfilled) {
            // onFulfilled BridgePro1 resolve 
            //  Promise BridgePro2
            return new Promise(function (resolve) {
                handle({
                    onFulfilled: onFulfilled || null,
                    resolve: resolve  // BridgePro2
                });
            });
        };
  • 9.MOPRO에서 비동기적인 작업이 완료되면resolve를 실행하고 핸드폰 번호 1865836을 전송하고resolve에 들어가서state를fulfilled,value를1865836로 설정하고 순환 MOPRO의 deferreds 수조를 지연합니다. 이때 수조는:
  • [
            {
                onFulfilled: resolve,   // BridgePro1 resolve
                resolve: resolve  // BridgePro2 resolve
            },
            {
                 onFulfilled: callback,
                resolve: resolve  // BridgePro3 resolve
            }
        ]
  • 10.handle 방법에 들어가서 첫 번째 값을 순환할 때 이때 deferred의 onFulfilled는 BridgePro1의 resolve로 이 resolve를 호출하고value(1865836)를 전송합니다. BridgePro1의 deferreds가 비어 있기 때문에 직접resolve는 BridgePro1을 제거합니다. 이때ret는 undefined이고 deferred의 resolve(BridgePro2의 resolve)를 실행합니다. 마찬가지로resolve는 BridgePro2를 제거하고 계속 순환하며 두 번째 값을 전송합니다. deferred의 onFulfilled는callback입니다.콜백을 실행하여value에 전송하고 핸드폰 번호 1865836을 출력합니다. 반환값은 undefined입니다. 따라서ret는 undefined이고 deferred의resolve(BridgePro3의resolve)를 실행하고 직접resolve는 BridgePro3
  • 를 제거합니다.
     function handle(deferred) {
            if (state === 'pending') {
                deferreds.push(deferred);
                return;
            }
        
            var ret = deferred.onFulfilled(value);
            deferred.resolve(ret);
        }
  • 11.이로써 실행이 완료되었습니다.user의 id를 통해user의mobilenumber
  • 를 바꿉니다

    후기:


    만약 내가 아래의 작법에 따라 계속 then을 내려가고 싶다면:
    IDfun()
        .then(MOfun)
        .then(callback)
        .then(callback)
        .then(callback)
    

    모든 콜백에 핸드폰 번호를 출력할 수 있습니다. 어떻게 써야 하나요?
    // callback
    function callback(res) {
        // doing something
        console.log(res)
        return res
    }
    

    요약:


    Promise는 무엇입니까, 글자 그대로 하나의 약속입니다. 제가 당신에게 하나의 약속을 했습니다. 당신은 기억하고 있습니다. 언제 현금으로 바꿀지 모르지만 당신에게 대답을 할 것입니다. 그다지 형상적이지 않은 비유를 할 것입니다. 제가 은행에 가서 일을 처리하면 틀림없이 하나의 번호를 먼저 받을 것입니다. 이 번호는 하나의 약속과 같습니다. 언제 당신을 불러야 할지 확실하지 않지만 당신을 불러야 합니다. 그리고 이때 당신은 당신의 일을 처리할 것입니다. 종합하면,즉, Promise 체인식의 원리 해석을 위해 잘못된 부분은 지적을 환영합니다

    좋은 웹페이지 즐겨찾기