使用Promise.prototype.catch.apply(this,...):为什么未处理的Promise拒绝?

时间:2018-12-28 00:13:48

标签: node.js typescript

我想为Promise.catch()编写一个包装程序,该包装程序执行一些默认操作,例如记录日志,然后调用.catch()拒绝Promise。

我试图理解我在示例代码的这两个简单位之间所表现出的行为差异。

为什么不起作用:

declare global {
    interface Promise<T> {
        catchWrapper(): Promise<T>;
    }
}
export {}

Promise.prototype.catchWrapper = function(){
    return Promise.prototype.catch.apply(this, e => { console.log(`An error occured: {e}`) });
};

async function f(): Promise<string> {
    throw new Error('error');
}

f().catchWrapper()

但是这样做:

declare global {
    interface Promise<T> {
        catchWrapper(errHandler: (errObj: any) => void): Promise<T>;
    }
}
export {}

Promise.prototype.catchWrapper = function(){
    return Promise.prototype.catch.apply(this, arguments);
};

async function f(): Promise<string> {
    throw new Error('An error');
}

f().catchWrapper(e => { console.log(`An error occured: ${e}`) });

第一个示例是在catchWrapper内部创建lambda函数,此示例生成未处理的promise拒绝。

第二个示例在catchWrapper外部创建lambda并将其传递。这按预期工作。

我是否发现this和lambda不兼容?

(我正在使用打字稿3.1.2和节点8.11.3)

修改: 第一个示例将arrow函数放置在数组内之后工作,如下所示:

return Promise.prototype.catch.apply(this,
    [e => { console.log(`An error occured: ${e}`) }]);

1 个答案:

答案 0 :(得分:2)

arguments是一个参数数组。因此,在您的第二个示例中:

Promise.prototype.catchWrapper = function(){
    return Promise.prototype.catch.apply(this, arguments);
};

您将参数作为数组传递,而不是像您期望的那样传递函数。您可以尝试传入arguments[0]来获取该功能。

或者您可以使用传播运算符:

Promise.prototype.catchWrapper = function(){
    return Promise.prototype.catch.apply(this, ...arguments);
};

但是简短的答案是您要传递一个参数数组,而不是将参数作为单独的参数。