javascript - 为什么我会收到“已使用未定义的参数调用承诺执行程序”警告?(Node.js)
问题描述
我正在尝试使用 Promises 在 Node.js (v12.20.1) 中创建一个流/惰性列表。我的基本想法是,Stream 可以简单地是一个 Promise,它解析为一个值和另一个 Stream。考虑到这一点,我想出了这个递归定义:
class Stream extends Promise {
constructor(executor) {
super((resolve, reject) =>
executor(
(value) =>
resolve({
head: value,
tail: new Stream(executor),
}),
reject
)
);
}
map(f) {
return this.then((cell) => {
return {
head: f(cell.head),
tail: cell.tail.map(f),
};
});
}
}
现在,这实际上完成了我所期望的所有操作,但只要解析了一个值,就会打印出一些警告消息。例如,使用事件发射器作为流的源:
> const Stream = require('./stream')
undefined
> const { EventEmitter } = require('events')
undefined
> const emitter = new EventEmitter();
undefined
> const stream = new Stream((yieldValue, reject) => emitter.once('foo', yieldValue));
undefined
> stream.map(console.log);
Stream [Promise] { <pending> }
> emitter.emit('foo', 1);
true
> 1
(node:22271) UnhandledPromiseRejectionWarning: TypeError: Promise executor has already been invoked with non-undefined arguments
at /wd/stream.js:4:13
at new Promise (<anonymous>)
at new Stream (/wd/stream.js:3:9)
at /wd/stream.js:8:31
at processTicksAndRejections (internal/process/task_queues.js:97:5)
(node:22271) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:22271) [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.
> emitter.emit('foo', 2);
true
> 2
(node:22271) UnhandledPromiseRejectionWarning: TypeError: Promise executor has already been invoked with non-undefined arguments
at /wd/stream.js:4:13
at new Promise (<anonymous>)
at new Stream (/wd/stream.js:3:9)
at /wd/stream.js:8:31
at processTicksAndRejections (internal/process/task_queues.js:97:5)
(node:22271) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
我真的不明白这里出了什么问题。我不明白多次调用 executor 的问题是什么,因为它只是一个函数,而且我当然不知道导致第二次警告的原因,因为据我所知,这里没有任何 Promise 被拒绝?
提前感谢您的帮助!
解决方案
问题是根据您子类this.then()
化的构造函数的合同构造一个新的承诺。Promise
为此,它使用一个执行程序调用您的Stream
构造函数,该执行程序将使用传递的解析器函数通过then
回调的结果解析新的 Promise。该执行程序预计只会被回调一次 - 但是您Stream
确实会多次调用它,一次立即调用,然后在调用期间resolve
调用。
在您的电话构建的各种承诺stream.map(console.log);
中,从未在任何地方处理过,有些似乎被拒绝了——如果你问我,这是正确的。
Stream 可能由递归链接的 Promise 1组成,但 Stream不是a Promise
。不要使用子类化!
1: 见这个或那个(也在这里)的例子。请注意,这个类似链表的概念已经被异步迭代器(博客文章)所取代,它现在有一个有状态的next()
方法。您还想看看异步生成器和 Observables 之间的区别是什么?.
推荐阅读
- aws-api-gateway - ApiGateway:如果基础路径为空,则只允许一个基础路径映射
- swift - 为什么使用 isEmpty 优于与空字符串文字的比较是 Swift?
- python - 错误的 scipy 拟合,即使初始猜测良好
- python - 将 os 模块添加到 PyCharm
- powerbi - 仅显示日期切片器 Power Bi 的第一个日期和最后一个日期的测量值
- javascript - 无法从 RESTFUL API 获得 Node 的正文响应
- enums - ldap 从模式中获取定义的枚举及其值
- prometheus - prometheus 规则因“不允许多对多匹配”而失败
- google-maps - 巴士站时刻表
- python - 选择具有 SQLAlchemy 继承的特定列