mirror of
https://gitee.com/coder-xiaomo/leetcode-problemset
synced 2025-01-11 02:58:13 +08:00
59 lines
16 KiB
JSON
59 lines
16 KiB
JSON
{
|
||
"data": {
|
||
"question": {
|
||
"questionId": "2797",
|
||
"questionFrontendId": "2694",
|
||
"categoryTitle": "JavaScript",
|
||
"boundTopicId": 2265814,
|
||
"title": "Event Emitter",
|
||
"titleSlug": "event-emitter",
|
||
"content": "<p>Design an <code>EventEmitter</code> class. This interface is similar (but with some differences) to the one found in Node.js or the Event Target interface of the DOM. The <code>EventEmitter</code> should allow for subscribing to events and emitting them.</p>\n\n<p>Your <code>EventEmitter</code> class should have the following two methods:</p>\n\n<ul>\n\t<li><strong>subscribe</strong> - This method takes in two arguments: the name of an event as a string and a callback function. This callback function will later be called when the event is emitted.<br />\n\tAn event should be able to have multiple listeners for the same event. When emitting an event with multiple callbacks, each should be called in the order in which they were subscribed. An array of results should be returned. You can assume no callbacks passed to <code>subscribe</code> are referentially identical.<br />\n\tThe <code>subscribe</code> method should also return an object with an <code>unsubscribe</code> method that enables the user to unsubscribe. When it is called, the callback should be removed from the list of subscriptions and <code>undefined</code> should be returned.</li>\n\t<li><strong>emit</strong> - This method takes in two arguments: the name of an event as a string and an optional array of arguments that will be passed to the callback(s). If there are no callbacks subscribed to the given event, return an empty array. Otherwise, return an array of the results of all callback calls in the order they were subscribed.</li>\n</ul>\n\n<p> </p>\n<p><strong class=\"example\">Example 1:</strong></p>\n\n<pre>\n<strong>Input:</strong> actions = ["EventEmitter", "emit", "subscribe", "subscribe", "emit"], values = [[], ["firstEvent", "function cb1() { return 5; }"], ["firstEvent", "function cb1() { return 5; }"], ["firstEvent"]]\n<strong>Output:</strong> [[],["emitted",[]],["subscribed"],["subscribed"],["emitted",[5,6]]]\n<strong>Explanation:</strong> \nconst emitter = new EventEmitter();\nemitter.emit("firstEvent"); // [], no callback are subscribed yet\nemitter.subscribe("firstEvent", function cb1() { return 5; });\nemitter.subscribe("firstEvent", function cb2() { return 6; });\nemitter.emit("firstEvent"); // [5, 6], returns the output of cb1 and cb2\n</pre>\n\n<p><strong class=\"example\">Example 2:</strong></p>\n\n<pre>\n<strong>Input:</strong> actions = ["EventEmitter", "subscribe", "emit", "emit"], values = [[], ["firstEvent", "function cb1(...args) { return args.join(','); }"], ["firstEvent", [1,2,3]], ["firstEvent", [3,4,6]]]\n<strong>Output:</strong> [[],["subscribed"],["emitted",["1,2,3"]],["emitted",["3,4,6"]]]\n<strong>Explanation: </strong>Note that the emit method should be able to accept an OPTIONAL array of arguents.\n\nconst emitter = new EventEmitter();\nemitter.subscribe("firstEvent, function cb1(...args) { return args.join(','); });\nemitter.emit("firstEvent", [1, 2, 3]); // ["1,2,3"]\nemitter.emit("firstEvent", [3, 4, 6]); // ["3,4,6"]\n</pre>\n\n<p><strong class=\"example\">Example 3:</strong></p>\n\n<pre>\n<strong>Input:</strong> actions = ["EventEmitter", "subscribe", "emit", "unsubscribe", "emit"], values = [[], ["firstEvent", "(...args) => args.join(',')"], ["firstEvent", [1,2,3]], [0], ["firstEvent", [4,5,6]]]\n<strong>Output:</strong> [[],["subscribed"],["emitted",["1,2,3"]],["unsubscribed",0],["emitted",[]]]\n<strong>Explanation:</strong>\nconst emitter = new EventEmitter();\nconst sub = emitter.subscribe("firstEvent", (...args) => args.join(','));\nemitter.emit("firstEvent", [1, 2, 3]); // ["1,2,3"]\nsub.unsubscribe(); // undefined\nemitter.emit("firstEvent", [4, 5, 6]); // [], there are no subscriptions\n</pre>\n\n<p> </p>\n<p><strong>Constraints:</strong></p>\n\n<ul>\n\t<li><code>1 <= actions.length <= 10</code></li>\n\t<li><code>values.length === actions.length</code></li>\n\t<li>All test cases are valid, e.g. you don't need to handle scenarios when unsubscribing from a non-existing subscription.</li>\n\t<li>There are only 4 different actions: <code>EventEmitter</code>, <code>emit</code>, <code>subscribe</code>, and <code>unsubscribe</code>.</li>\n\t<li>The <code>EventEmitter</code> action doesn't take any arguments.</li>\n\t<li>The <code>emit</code> action takes between either 1 or 2 arguments. The first argument is the name of the event we want to emit, and the 2nd argument is passed to the callback functions.</li>\n\t<li>The <code>subscribe</code> action takes 2 arguments, where the first one is the event name and the second is the callback function.</li>\n\t<li>The <code>unsubscribe</code> action takes one argument, which is the 0-indexed order of the subscription made before.</li>\n</ul>\n",
|
||
"translatedTitle": "事件发射器",
|
||
"translatedContent": "<p>设计一个 <code>EventEmitter</code> 类。这个接口与 Node.js 或 DOM 的 Event Target 接口相似,但有一些差异。<code>EventEmitter</code> 应该允许订阅事件和触发事件。</p>\n\n<p>你的 <code>EventEmitter</code> 类应该有以下两个方法:</p>\n\n<ul>\n\t<li><strong>subscribe</strong> - 这个方法接收两个参数:一个作为字符串的事件名和一个回调函数。当事件被触发时,这个回调函数将被调用。 一个事件应该能够有多个监听器。当触发带有多个回调函数的事件时,应按照订阅的顺序依次调用每个回调函数。应返回一个结果数组。你可以假设传递给 <code>subscribe</code> 的回调函数都不是引用相同的。 <code>subscribe</code> 方法还应返回一个对象,其中包含一个 <code>unsubscribe</code> 方法,使用户可以取消订阅。当调用 <code>unsubscribe</code> 方法时,回调函数应该从订阅列表中删除,并返回 undefined。</li>\n\t<li><strong>emit</strong> - 这个方法接收两个参数:一个作为字符串的事件名和一个可选的参数数组,这些参数将传递给回调函数。如果没有订阅给定事件的回调函数,则返回一个空数组。否则,按照它们被订阅的顺序返回所有回调函数调用的结果数组。</li>\n</ul>\n\n<p> </p>\n\n<p><strong>示例 1:</strong></p>\n\n<pre>\n<b>输入:</b>actions = [\"EventEmitter\", \"emit\", \"subscribe\", \"subscribe\", \"emit\"], values = [[], [\"firstEvent\", \"function cb1() { return 5; }\"], [\"firstEvent\", \"function cb1() { return 5; }\"], [\"firstEvent\"]]\n<b>输出:</b>[[],[\"emitted\",[]],[\"subscribed\"],[\"subscribed\"],[\"emitted\",[5,6]]]\n<b>解释:</b>\nconst emitter = new EventEmitter();\nemitter.emit(\"firstEvent\"); // [], 还没有订阅任何回调函数\nemitter.subscribe(\"firstEvent\", function cb1() { return 5; });\nemitter.subscribe(\"firstEvent\", function cb2() { return 6; });\nemitter.emit(\"firstEvent\"); // [5, 6], 返回 cb1 和 cb2 的输出\n</pre>\n\n<p><strong>示例 2:</strong></p>\n\n<pre>\n<b>输入:</b>actions = [\"EventEmitter\", \"subscribe\", \"emit\", \"emit\"], values = [[], [\"firstEvent\", \"function cb1(...args) { return args.join(','); }\"], [\"firstEvent\", [1,2,3]], [\"firstEvent\", [3,4,6]]]\n<b>输出:</b>[[],[\"subscribed\"],[\"emitted\",[\"1,2,3\"]],[\"emitted\",[\"3,4,6\"]]]\n<strong>解释:</strong>注意 emit 方法应该能够接受一个可选的参数数组。\n\nconst emitter = new EventEmitter();\nemitter.subscribe(\"firstEvent, function cb1(...args) { return args.join(','); });\nemitter.emit(\"firstEvent\", [1, 2, 3]); // [\"1,2,3\"]\nemitter.emit(\"firstEvent\", [3, 4, 6]); // [\"3,4,6\"]\n</pre>\n\n<p><strong>示例 3:</strong></p>\n\n<pre>\n<b>输入:</b>actions = [\"EventEmitter\", \"subscribe\", \"emit\", \"unsubscribe\", \"emit\"], values = [[], [\"firstEvent\", \"(...args) => args.join(',')\"], [\"firstEvent\", [1,2,3]], [0], [\"firstEvent\", [4,5,6]]]\n<b>输出:</b>[[],[\"subscribed\"],[\"emitted\",[\"1,2,3\"]],[\"unsubscribed\",0],[\"emitted\",[]]]\n<b>解释:</b>\nconst emitter = new EventEmitter();\nconst sub = emitter.subscribe(\"firstEvent\", (...args) => args.join(','));\nemitter.emit(\"firstEvent\", [1, 2, 3]); // [\"1,2,3\"]\nsub.unsubscribe(); // undefined\nemitter.emit(\"firstEvent\", [4, 5, 6]); // [], 没有订阅者\n</pre>\n\n<p> </p>\n\n<p><strong>提示:</strong></p>\n\n<ul>\n\t<li><code>1 <= actions.length <= 10</code></li>\n\t<li><code>values.length === actions.length</code></li>\n\t<li>所有测试用例都是有效的。例如,你不需要处理取消一个不存在的订阅的情况。</li>\n\t<li>只有 4 种不同的操作:<code>EventEmitter</code>、<code>emit</code>、<code>subscribe</code> 和 <code>unsubscribe</code> 。 <code>EventEmitter</code> 操作没有参数。</li>\n\t<li><code>emit</code> 操作接收 1 或 2 个参数。第一个参数是要触发的事件名,第二个参数传递给回调函数。</li>\n\t<li><code>subscribe</code> 操作接收 2 个参数,第一个是事件名,第二个是回调函数。</li>\n\t<li><code>unsubscribe</code> 操作接收一个参数,即之前进行订阅的顺序(从 0 开始)。</li>\n</ul>\n",
|
||
"isPaidOnly": false,
|
||
"difficulty": "Medium",
|
||
"likes": 1,
|
||
"dislikes": 0,
|
||
"isLiked": null,
|
||
"similarQuestions": "[]",
|
||
"contributors": [],
|
||
"langToValidPlayground": "{\"cpp\": false, \"java\": true, \"python\": true, \"python3\": false, \"mysql\": false, \"mssql\": false, \"oraclesql\": false, \"c\": false, \"csharp\": false, \"javascript\": false, \"ruby\": false, \"bash\": false, \"swift\": false, \"golang\": false, \"scala\": false, \"html\": false, \"pythonml\": false, \"kotlin\": false, \"rust\": false, \"php\": false, \"typescript\": false, \"racket\": false, \"erlang\": false, \"elixir\": false, \"dart\": false}",
|
||
"topicTags": [],
|
||
"companyTagStats": null,
|
||
"codeSnippets": [
|
||
{
|
||
"lang": "JavaScript",
|
||
"langSlug": "javascript",
|
||
"code": "class EventEmitter {\n subscribe(event, cb) {\n \n return {\n unsubscribe: () => {\n\n }\n };\n }\n\n emit(event, args = []) {\n\n }\n}\n\n/**\n * const emitter = new EventEmitter();\n *\n * // Subscribe to the onClick event with onClickCallback\n * function onClickCallback() { return 99 }\n * const sub = emitter.subscribe('onClick', onClickCallback);\n *\n * emitter.emit('onClick'); // [99]\n * sub.unsubscribe(); // undefined\n * emitter.emit('onClick'); // []\n */",
|
||
"__typename": "CodeSnippetNode"
|
||
},
|
||
{
|
||
"lang": "TypeScript",
|
||
"langSlug": "typescript",
|
||
"code": "type Callback = (...args: any[]) => any;\ntype Subscription = {\n unsubscribe: () => void\n}\n\nclass EventEmitter {\n subscribe(eventName: string, callback: Callback): Subscription {\n\n return {\n unsubscribe: () => {\n\n }\n };\n }\n\n emit(eventName: string, args: any[] = []): any {\n\n }\n}\n\n/**\n * const emitter = new EventEmitter();\n *\n * // Subscribe to the onClick event with onClickCallback\n * function onClickCallback() { return 99 }\n * const sub = emitter.subscribe('onClick', onClickCallback);\n *\n * emitter.emit('onClick'); // [99]\n * sub.unsubscribe(); // undefined\n * emitter.emit('onClick'); // []\n */",
|
||
"__typename": "CodeSnippetNode"
|
||
}
|
||
],
|
||
"stats": "{\"totalAccepted\": \"154\", \"totalSubmission\": \"236\", \"totalAcceptedRaw\": 154, \"totalSubmissionRaw\": 236, \"acRate\": \"65.3%\"}",
|
||
"hints": [],
|
||
"solution": null,
|
||
"status": null,
|
||
"sampleTestCase": "[\"EventEmitter\", \"emit\", \"subscribe\", \"subscribe\", \"emit\"]\n[[], [\"firstEvent\"], [\"firstEvent\", \"function cb1() { return 5; }\"], [\"firstEvent\", \"function cb1() { return 6; }\"], [\"firstEvent\"]]",
|
||
"metaData": "{\n \"name\": \"EventEmitter\",\n \"params\": [\n {\n \"type\": \"string[]\",\n \"name\": \"actions\"\n },\n {\n \"type\": \"character[][]\",\n \"name\": \"values\"\n }\n ],\n \"return\": {\n \"type\": \"void\"\n },\n \"languages\": [\n \"typescript\",\n \"javascript\"\n ],\n \"manual\": true\n}",
|
||
"judgerAvailable": true,
|
||
"judgeType": "large",
|
||
"mysqlSchemas": [],
|
||
"enableRunCode": true,
|
||
"envInfo": "{\"javascript\":[\"JavaScript\",\"<p>\\u7248\\u672c\\uff1a<code>Node.js 16.13.2<\\/code><\\/p>\\r\\n\\r\\n<p>\\u60a8\\u7684\\u4ee3\\u7801\\u5728\\u6267\\u884c\\u65f6\\u5c06\\u5e26\\u4e0a <code>--harmony<\\/code> \\u6807\\u8bb0\\u6765\\u5f00\\u542f <a href=\\\"http:\\/\\/node.green\\/\\\" target=\\\"_blank\\\">\\u65b0\\u7248ES6\\u7279\\u6027<\\/a>\\u3002<\\/p>\\r\\n\\r\\n<p><a href=\\\"https:\\/\\/lodash.com\\\" target=\\\"_blank\\\">lodash.js<\\/a> \\u5e93\\u5df2\\u7ecf\\u9ed8\\u8ba4\\u88ab\\u5305\\u542b\\u3002<\\/p>\\r\\n\\r\\n<p> \\u5982\\u9700\\u4f7f\\u7528\\u961f\\u5217\\/\\u4f18\\u5148\\u961f\\u5217\\uff0c\\u60a8\\u53ef\\u4f7f\\u7528 <a href=\\\"https:\\/\\/github.com\\/datastructures-js\\/priority-queue\\/tree\\/fb4fdb984834421279aeb081df7af624d17c2a03\\\" target=\\\"_blank\\\"> datastructures-js\\/priority-queue@5.3.0<\\/a> \\u548c <a href=\\\"https:\\/\\/github.com\\/datastructures-js\\/queue\\/tree\\/e63563025a5a805aa16928cb53bcd517bfea9230\\\" target=\\\"_blank\\\"> datastructures-js\\/queue@4.2.1<\\/a>\\u3002<\\/p>\"],\"typescript\":[\"TypeScript\",\"<p>TypeScript 4.5.4<\\/p>\\r\\n\\r\\n<p>Compile Options: --alwaysStrict --strictBindCallApply --strictFunctionTypes --target ES2020<\\/p>\\r\\n\\r\\n<p><a href=\\\"https:\\/\\/lodash.com\\\" target=\\\"_blank\\\">lodash.js<\\/a> \\u5e93\\u5df2\\u7ecf\\u9ed8\\u8ba4\\u88ab\\u5305\\u542b\\u3002<\\/p>\\r\\n\\r\\n<p> \\u5982\\u9700\\u4f7f\\u7528\\u961f\\u5217\\/\\u4f18\\u5148\\u961f\\u5217\\uff0c\\u60a8\\u53ef\\u4f7f\\u7528 <a href=\\\"https:\\/\\/github.com\\/datastructures-js\\/priority-queue\\/tree\\/fb4fdb984834421279aeb081df7af624d17c2a03\\\" target=\\\"_blank\\\"> datastructures-js\\/priority-queue@5.3.0<\\/a> \\u548c <a href=\\\"https:\\/\\/github.com\\/datastructures-js\\/queue\\/tree\\/e63563025a5a805aa16928cb53bcd517bfea9230\\\" target=\\\"_blank\\\"> datastructures-js\\/queue@4.2.1<\\/a>\\u3002<\\/p>\"]}",
|
||
"book": null,
|
||
"isSubscribed": false,
|
||
"isDailyQuestion": false,
|
||
"dailyRecordStatus": null,
|
||
"editorType": "CKEDITOR",
|
||
"ugcQuestionId": null,
|
||
"style": "LEETCODE",
|
||
"exampleTestcases": "[\"EventEmitter\", \"emit\", \"subscribe\", \"subscribe\", \"emit\"]\n[[], [\"firstEvent\"], [\"firstEvent\", \"function cb1() { return 5; }\"], [\"firstEvent\", \"function cb1() { return 6; }\"], [\"firstEvent\"]]\n[\"EventEmitter\", \"subscribe\", \"emit\", \"emit\"]\n[[], [\"firstEvent\", \"function cb1(...args) { return args.join(','); }\"], [\"firstEvent\", [1,2,3]], [\"firstEvent\", [3,4,6]]]\n[\"EventEmitter\", \"subscribe\", \"emit\", \"unsubscribe\", \"emit\"]\n[[], [\"firstEvent\", \"(...args) => args.join(',')\"], [\"firstEvent\", [1,2,3]], [0], [\"firstEvent\", [4,5,6]]]",
|
||
"__typename": "QuestionNode"
|
||
}
|
||
}
|
||
} |