在javascript

时间:2016-09-01 14:04:10

标签: javascript promise timeout

在我的测试中,有时我会得到超时,看看超时之前待处理的承诺在哪里是非常有用的,这样我就知道什么承诺最有可能在"总是待定状态"。

有办法吗?

以下是一个示例代码:

Promise.resolve().then(function firstFunction() {
    console.log(1);
    return 1;
}).then(function () {
    return new Promise(function secondFunction(resolve, reject) {
        // NEVER RESOLVING PROMISE
        console.log(2);
    });
}).then(function thirdFunction() {
    // function that will never be called
    console.log(3);
})

setTimeout(function timeoutTest() {
    const pendingPromises = [];// ??????????? how do I get the pendingPromises
    console.log(pendingPromises);
    process.exit();
}, 5000);

如果可能的话,我希望获得pendingPromises函数的名称和承诺secondFunction的堆栈跟踪,因为它永远不会解析。

2 个答案:

答案 0 :(得分:3)

承诺链是逐步设计的,以便在其成功路径上提供价值,或者沿着其错误路径提供“理由”。它不是设计用于在某个任意时间点查询“快照”被其同化的个人承诺的状态。

因此,承诺链没有“自然”的方式来做你所要求的。

你需要设计一个机制:

  • 登记利益承诺。
  • 跟踪每个已注册的承诺的状态(如果承诺实施尚未提供)。
  • 按要求撤销已登记的承诺,按州过滤。

沿着这些方向的构造函数将完成这项工作:

function Inspector() {
    var arr = [];
    this.add = function(p, label) {
        p.label = label || '';
        if(!p.state) {
            p.state = 'pending';
            p.then(
                function(val) { p.state = 'resolved'; },
                function(e) { p.state = 'rejected'; }
            );
        }
        arr.push(p);
        return p;
    };
    this.getPending  = function() {
        return arr.filter(function(p) { return p.state === 'pending'; });
    };
    this.getSettled = function() {
        return arr.filter(function(p) { return p.state !== 'pending'; });
    };
    this.getResolved = function() {
        return arr.filter(function(p) { return p.state === 'resolved'; });
    };
    this.getRejected = function() {
        return arr.filter(function(p) { return p.state === 'rejected'; });
    };
    this.getAll  = function() {
        return arr.slice(0); // return a copy of arr, not arr itself.
    };
};

问题所需的唯一方法是.add().getPending()。提供其他完整性。

您现在可以写:

var inspector = new Inspector();

Promise.resolve().then(function() {
    console.log(1);
}).then(function() {
    var p = new Promise(function(resolve, reject) {
        // NEVER RESOLVING PROMISE
        console.log(2);
    });
    return inspector.add(p, '2');
}).then(function() {
    // function that will never be called
    console.log(3);
});

setTimeout(function() {
    const pendingPromises = inspector.getPending();
    console.log(pendingPromises);
    process.exit();
}, 5000);

<强> fiddle

Inspector的使用并不局限于承诺链所同化的承诺。它可以用于任意一组承诺,例如与Promise.all()汇总的集合:

promise_1 = ...;
promise_2 = ...;
promise_3 = ...;

var inspector = new Inspector();
inspector.add(promise_1, 'promise 1');
inspector.add(promise_2, 'promise 2');
inspector.add(promise_3, 'promise 3');

var start = Date.now();
var intervalRef = setInterval(function() {
    console.log(Date.now() - start + ': ' + inspector.getSettled().length + ' of ' + inspector.getAll().length + ' promises have settled');
}, 50);

Promise.all(inspector.getAll()).then(successHandler).catch(errorHandler).finally(function() {
    clearInterval(intervalRef);
});

答案 1 :(得分:1)

我建议使用Bluebird这样的库比本机承诺快〜6倍,提供有用的警告和其他有用的方法,比如 - timeout可能会帮助你解决这个问题。