javascript - Node 未处理的 Promise 问题

标签 javascript node.js promise

我之前问过这里的问题: Retaining Data across multiple promise chains

我最终使用了 T.J.克劳德对我的基本代码的回答,此后做了很多更改。但我注意到 Node 中有一些奇怪的东西我似乎无法克服。我回到他提供的基本代码,问题似乎也存在。

示例如下:

"use strict";

// For tracking our status
class Status {
    constructor(total = 0, count = 0) {
        this.id = ++Status.id;
        this.total = total;
        this.count = count;
    }
    addCall() {
        ++this.total;
        return this;
    }
    addProgress() {
        ++this.count;
        return this;
    }
    toString() {
        return `[S${this.id}]: Total: ${this.total}, Count: ${this.count}`;
    }
}
Status.id = 0;

// The promise subclass
class RepoPromise extends Promise {
    constructor(executor) {
        super(executor);
        this.s = new Status();
    }
    // Utility method to wrap `then`/`catch` callbacks so we hook into when they're called
    _wrapCallbacks(...callbacks) {
        return callbacks.filter(c => c).map(c => value => this._handleCallback(c, value));
    }
    // Utility method for when the callback should be called: We track that we've seen
    // the call then execute the callback
    _handleCallback(callback, value) {
        this.s.addProgress();
        console.log("Progress: " + this.s);
        return callback(value);
    }
    // Standard `then`, but overridden so we track what's going on, including copying
    // our status object to the new promise before returning it
    then(onResolved, onRejected) {
        this.s.addCall();
        console.log("Added: " + this.s);
        const newPromise = super.then(...this._wrapCallbacks(onResolved, onRejected));
        newPromise.s = this.s;
        return newPromise;
    }
    // Standard `catch`, doing the same things as `then`
    catch(onRejected) {
        this.s.addCall();
        console.log("Added: " + this.s);
        const newPromise = super.catch(...this._wrapCallbacks(onRejected));
        newPromise.s = this.s;
        return newPromise;
    }
}

// Create a promise we'll resolve after a random timeout
function delayedGratification() {
    return new Promise(resolve => {
        setTimeout(_ => {
            resolve();
        }, Math.random() * 1000);
    });
}

// Run! Note we follow both kinds of paths: Chain and diverge:
const rp = RepoPromise.resolve('Test');
rp.then(function(scope) {
    return new Promise((resolve, reject) => {
        console.log('  Rejected')
        reject(scope)
    })
})
.catch(e => {console.log('Never Makes it')})

当我使用以下命令运行此命令时:node test.js 我得到以下输出

Added: [S1]: Total: 1, Count: 0
Added: [S1]: Total: 2, Count: 0
Added: [S1]: Total: 3, Count: 0
Progress: [S1]: Total: 3, Count: 1
  Rejected
(node:29364) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Test
(node:29364) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

请注意,“never make it” 的控制台日志不存在,另请注意,我已经修复了 catch 运行两次的问题,因为它是简单的语法糖对于 then(null, function(){}),因此您可以忽略它。

为什么 catch 没有按我的预期工作?当我以正常的 promise 执行此操作时,不会出现任何问题,如下所示。所以我知道 _wrapCallbacks 导致了这个问题,我只是不确定为什么,或者如何修复它。

const rp = Promise.resolve('Test');
rp.then(function(scope) {
    return new Promise((resolve, reject) => {
        console.log('  Rejected')
        reject(scope)
    })
})
.catch(e => {console.log('Makes it')})

最佳答案

您的 promise 的 catch 实现不起作用。请注意, native catch 实现为 return this.then(null, callback) - 调用 super.catch 将直接返回到您的 然后实现。

并且您的 then 实现有一个重大错误:它不喜欢在函数之前获取 null 参数。当您执行此操作时,观察上面的调用中会发生什么:

_wrapCallbacks(...callbacks) {
    return callbacks.filter(c => c).map(…);
//                  ^^^^^^^^^^^^^^^
}
then(onResolved, onRejected) {
    …
    const newPromise = super.then(...this._wrapCallbacks(onResolved, onRejected));
    …
}

这将简单地从参数数组中删除 null 并将 onrejected 回调作为 onfulfilled 传递。您需要删除过滤器并在映射函数中使用三元组:

_wrapCallbacks(...callbacks) {
    return callbacks.map(c => typeof c == "function"
      ? value => this._handleCallback(c, value)
      : c);
}

您也可以直接删除被覆盖的catch

关于javascript - Node 未处理的 Promise 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46775769/

相关文章:

node.js - 模块 '"typeorm "' has no exported member ' DataSource' 和 'DataSourceOptions'

javascript - React Native 中的 Promise

jQuery,等待方法完成然后触发操作

javascript - 每个 JS : what's the promises equivalent of async.?

javascript - 如何创建泛型类型别名?

javascript - 使用jquery分页插件进行分页

javascript - 如何在ejs(javascriptmvc)中指定相对图像路径

javascript - 选择字段时的模态表单清除

javascript - 如何在Windows 8上设置nodejs + nginx

javascript - 在 puppeteer 中获取具有特定类的图像 src