본문 바로가기
개발 및 운영/Node.JS

멈춘 Promise 디버깅 하기

by Joseph.Lee 2020. 4. 27.

소스 초반에..

import * as uuids from 'uuid';
const promiseMap: Map < string, any > = new Map();
const OrigPromise: PromiseConstructor = global.Promise as PromiseConstructor;
function arrayArguments(input: IArguments): any[] {
    const arr = [];
    for(let i=0; i<input.length; i++) {
        arr[i] = input[i];
    }
    return arr;
}
global.Promise = function(func: any) {
    const stack = new Error().stack;
    return new OrigPromise((resolve, reject) => {
        const uuid = uuids.v4();
        promiseMap.set(uuid, {
            uuid,
            stack
        });
        func(function() {
            promiseMap.delete(uuid);
            resolve.call(null, ...arrayArguments(arguments));
        }, (err: any) => {
            promiseMap.delete(uuid);
            reject(err);
        });
    });
}

참고로 위는 typescript 소스이다.

위 내용을 추가한 뒤에 멈춘 Promise를 보고 싶을 때 showPendingPromise()을 호출하면 된다.

대충

setTimeout(() => showPendingPromise(), 1000);

이렇게 몇초뒤에 출력해도 되구...

그럼 Promise를 생성한 스택프레임을 보여준다.

===== 추가 =====
Proxy가 사용가능한 경우 아래가 더 낫다

import * as uuids from 'uuid';
const promiseMap: Map < string, any > = new Map();
const OrigPromise: PromiseConstructor = global.Promise as PromiseConstructor;
function arrayArguments(input: IArguments): any[] {
    const arr = [];
    for(let i=0; i<input.length; i++) {
        arr[i] = input[i];
    }
    return arr;
}
function newPromise(func: any) {
    const stack = new Error().stack;
    return new OrigPromise((resolve, reject) => {
        const uuid = uuids.v4();
        promiseMap.set(uuid, {
            uuid,
            stack
        });
        func(function() {
            promiseMap.delete(uuid);
            resolve.call(null, ...arrayArguments(arguments));
        }, (err: any) => {
            promiseMap.delete(uuid);
            reject(err);
        });
    });
}

function showPendingPromise() {
    for (let item of promiseMap.entries()) {
        console.log(item[1]);
    }
}

setInterval(() => showPendingPromise(), 3000);

(global as any).Promise = new Proxy((global as any).Promise, {
    construct(target: any, argArray: any, newTarget?: any): object {
        return newPromise(argArray[0]);
    }
});
반응형

댓글