如果sendToSocket成功,为什么setTimeout def.reject代码不会运行?

时间:2016-09-21 10:28:24

标签: javascript node.js

如果sendToSocket成功,为什么setTimeout def.reject代码不能运行?

this.send = function(type, body) {
    var def = Promise.defer();
    try{
        sendToSocket({...});
        setTimeout(function() { // if the send sendToSocket Succeeds how does nodejs/javascript know not to run the timeout code after 10 seconds?
            def.reject(new Error("timeout"));
        }, 10000);
    }catch(err){
        logger.error('error');
        def.reject(err);
    }

    return def.promise;
};

1 个答案:

答案 0 :(得分:2)

正如评论所说,承诺的状态只能改变一次,从待决到履行或拒绝。一旦承诺得到履行,拒绝将被忽略。

此外,它被认为是更好的形式使用Promise.defer()而是使用new Promise构造函数:

return new Promise(function(resolve, reject) {
    sendToSocket({...}); // call resolve() here
    setTimeout(function() { reject(new Error("timeout")); }, 10000)
});

你注意到这里没有try/catch,因为在Promise构造函数中,任何抛出的异常都会自动转换为拒绝。

我会做的另一个事情是将方法与超时分开,如下所示:

function withTimeout(delay, fn) {
    return function() {
        return Promise.race([ // race between...
            // Promise that rejects after "delay" ms
            new Promise(function(resolve, reject) {
                setTimeout(function() { reject(new Error("timeout")); }, delay);
            }), // and...
            // Promise that actually does the action

            // The call to `Promise.resolve()` is to ensure we get a Promise
            // even if the function doesn't return one.
            Promise.resolve(fn.apply(null, arguments))
        ]);
    };
}

this.send = function() {
    return new Promise(function(resolve, reject) {
        sendToSocket({...}); // call resolve here, or reject on error.
                             // thrown errors will be converted anyway
    });
};

this.sendWithTimeout = withTimeout(10000, this.send.bind(this));

调用withTimeout将返回新函数,返回带有超时选项的Promise。

Promise.race()返回一个Promise,它在传递的Promises数组中的第一个Promise解析或拒绝时解析(或拒绝)。我们在this.send()返回的实际承诺和在超时时拒绝的承诺之间竞赛

这意味着您的this.send()功能仅处理实际发送。超时是您通过抽象添加的细节。