{ "data": { "question": { "questionId": "2821", "questionFrontendId": "2715", "categoryTitle": "JavaScript", "boundTopicId": 2293968, "title": "Timeout Cancellation", "titleSlug": "timeout-cancellation", "content": "

Given a function fn, an array of arguments args, and a timeout t in milliseconds, return a cancel function cancelFn.

\n\n

After a delay of cancelTimeMs, the returned cancel function cancelFn will be invoked.

\n\n
\nsetTimeout(cancelFn, cancelTimeMs)\n
\n\n

Initially, the execution of the function fn should be delayed by t milliseconds.

\n\n

If, before the delay of t milliseconds, the function cancelFn is invoked, it should cancel the delayed execution of fn. Otherwise, if cancelFn is not invoked within the specified delay t, fn should be executed with the provided args as arguments.

\n\n

 

\n

Example 1:

\n\n
\nInput: fn = (x) => x * 5, args = [2], t = 20\nOutput: [{"time": 20, "returned": 10}]\nExplanation: \nconst cancelTimeMs = 50;\nconst cancelFn = cancellable((x) => x * 5, [2], 20);\nsetTimeout(cancelFn, cancelTimeMs);\n\nThe cancellation was scheduled to occur after a delay of cancelTimeMs (50ms), which happened after the execution of fn(2) at 20ms.\n
\n\n

Example 2:

\n\n
\nInput: fn = (x) => x**2, args = [2], t = 100\nOutput: []\nExplanation: \nconst cancelTimeMs = 50;\nconst cancelFn = cancellable((x) => x**2, [2], 100);\nsetTimeout(cancelFn, cancelTimeMs);\n\nThe cancellation was scheduled to occur after a delay of cancelTimeMs (50ms), which happened before the execution of fn(2) at 100ms, resulting in fn(2) never being called.\n
\n\n

Example 3:

\n\n
\nInput: fn = (x1, x2) => x1 * x2, args = [2,4], t = 30\nOutput: [{"time": 30, "returned": 8}]\nExplanation: \nconst cancelTimeMs = 100;\nconst cancelFn = cancellable((x1, x2) => x1 * x2, [2,4], 30);\nsetTimeout(cancelFn, cancelTimeMs);\n\nThe cancellation was scheduled to occur after a delay of cancelTimeMs (100ms), which happened after the execution of fn(2,4) at 30ms.\n
\n\n

 

\n

Constraints:

\n\n\n", "translatedTitle": "执行可取消的延迟函数", "translatedContent": "

给定一个函数 fn ,一个参数数组 args 和一个以毫秒为单位的超时时间 t ,返回一个取消函数 cancelFn

\n\n

cancelTimeMs 的延迟后,返回的取消函数 cancelFn 将被调用。

\n\n
\nsetTimeout(cancelFn, cancelTimeMs)\n
\n\n

最初,函数 fn 的执行应该延迟 t 毫秒。

\n\n

如果在 t 毫秒的延迟之前调用了函数 cancelFn,它应该取消 fn 的延迟执行。否则,如果在指定的延迟 t 内没有调用 cancelFn,则应执行 fn,并使用提供的 args 作为参数。

\n\n

 

\n\n

示例 1:

\n\n
\n输入:fn = (x) => x * 5, args = [2], t = 20\n输出:[{\"time\": 20, \"returned\": 10}]\n解释:\nconst cancelTimeMs = 50;\nconst cancelFn = cancellable((x) => x * 5, [2], 20);\nsetTimeout(cancelFn, cancelTimeMs);\n\n取消操作被安排在延迟了 cancelTimeMs(50毫秒)后进行,这发生在 fn(2) 在20毫秒时执行之后。
\n\n

示例 2:

\n\n
\n输入:fn = (x) => x**2, args = [2], t = 100\n输出:[]\n解释:\nconst cancelTimeMs = 50;\nconst cancelFn = cancellable((x) => x**2, [2], 100);\nsetTimeout(cancelFn, cancelTimeMs);\n\n取消操作被安排在延迟了 cancelTimeMs(50毫秒)后进行,这发生在 fn(2) 在100毫秒时执行之前,导致 fn(2) 从未被调用。\n
\n\n

示例 3:

\n\n
\n输入:fn = (x1, x2) => x1 * x2, args = [2,4], t = 30\n输出:[{\"time\": 30, \"returned\": 8}]\n解释:\nconst cancelTimeMs = 100;\nconst cancelFn = cancellable((x1, x2) => x1 * x2, [2,4], 30);\nsetTimeout(cancelFn, cancelTimeMs);\n\n取消操作被安排在延迟了 cancelTimeMs(100毫秒)后进行,这发生在 fn(2,4) 在30毫秒时执行之后。\n
\n\n

 

\n\n

提示:

\n\n\n", "isPaidOnly": false, "difficulty": "Easy", "likes": 6, "dislikes": 0, "isLiked": null, "similarQuestions": "[]", "contributors": [], "langToValidPlayground": "{\"cpp\": true, \"java\": true, \"python\": true, \"python3\": true, \"mysql\": false, \"mssql\": false, \"oraclesql\": false, \"c\": false, \"csharp\": false, \"javascript\": false, \"typescript\": false, \"bash\": false, \"php\": false, \"swift\": false, \"kotlin\": false, \"dart\": false, \"golang\": false, \"ruby\": false, \"scala\": false, \"html\": false, \"pythonml\": false, \"rust\": false, \"racket\": false, \"erlang\": false, \"elixir\": false, \"pythondata\": false, \"react\": false, \"vanillajs\": false, \"postgresql\": false, \"cangjie\": false}", "topicTags": [], "companyTagStats": null, "codeSnippets": [ { "lang": "JavaScript", "langSlug": "javascript", "code": "/**\n * @param {Function} fn\n * @param {Array} args\n * @param {number} t\n * @return {Function}\n */\nvar cancellable = function(fn, args, t) {\n \n};\n\n/**\n * const result = [];\n *\n * const fn = (x) => x * 5;\n * const args = [2], t = 20, cancelTimeMs = 50;\n *\n * const start = performance.now();\n *\n * const log = (...argsArr) => {\n * const diff = Math.floor(performance.now() - start);\n * result.push({\"time\": diff, \"returned\": fn(...argsArr)});\n * }\n * \n * const cancel = cancellable(log, args, t);\n *\n * const maxT = Math.max(t, cancelTimeMs);\n * \n * setTimeout(cancel, cancelTimeMs);\n *\n * setTimeout(() => {\n * console.log(result); // [{\"time\":20,\"returned\":10}]\n * }, maxT + 15)\n */", "__typename": "CodeSnippetNode" }, { "lang": "TypeScript", "langSlug": "typescript", "code": "type JSONValue = null | boolean | number | string | JSONValue[] | { [key: string]: JSONValue };\ntype Fn = (...args: JSONValue[]) => void\n\nfunction cancellable(fn: Fn, args: JSONValue[], t: number): Function {\n \n};\n\n/**\n * const result = [];\n *\n * const fn = (x) => x * 5;\n * const args = [2], t = 20, cancelTimeMs = 50;\n *\n * const start = performance.now();\n *\n * const log = (...argsArr) => {\n * const diff = Math.floor(performance.now() - start);\n * result.push({\"time\": diff, \"returned\": fn(...argsArr)});\n * }\n * \n * const cancel = cancellable(log, args, t);\n *\n * const maxT = Math.max(t, cancelTimeMs);\n * \n * setTimeout(cancel, cancelTimeMs);\n *\n * setTimeout(() => {\n * console.log(result); // [{\"time\":20,\"returned\":10}]\n * }, maxT + 15)\n */", "__typename": "CodeSnippetNode" } ], "stats": "{\"totalAccepted\": \"5.1K\", \"totalSubmission\": \"6.1K\", \"totalAcceptedRaw\": 5069, \"totalSubmissionRaw\": 6110, \"acRate\": \"83.0%\"}", "hints": [], "solution": null, "status": null, "sampleTestCase": "(x) => x * 5\n[2]\n20\n50", "metaData": "{\n \"name\": \"cancellable\",\n \"params\": [\n {\n \"name\": \"fn\",\n \"type\": \"string\"\n },\n {\n \"type\": \"string\",\n \"name\": \"args\"\n },\n {\n \"type\": \"integer\",\n \"name\": \"t\"\n },\n {\n \"type\": \"integer\",\n \"name\": \"cancelTimeMs\"\n }\n ],\n \"return\": {\n \"type\": \"integer\"\n },\n \"languages\": [\n \"javascript\",\n \"typescript\"\n ],\n \"manual\": true\n}", "judgerAvailable": true, "judgeType": "large", "mysqlSchemas": [], "enableRunCode": true, "envInfo": "{\"javascript\":[\"JavaScript\",\"

\\u7248\\u672c\\uff1aNode.js 20.10.0<\\/code><\\/p>\\r\\n\\r\\n

\\u60a8\\u7684\\u4ee3\\u7801\\u5728\\u6267\\u884c\\u65f6\\u5c06\\u5e26\\u4e0a --harmony<\\/code> \\u6807\\u8bb0\\u6765\\u5f00\\u542f \\u65b0\\u7248ES6\\u7279\\u6027<\\/a>\\u3002<\\/p>\\r\\n\\r\\n

lodash.js<\\/a> \\u5e93\\u5df2\\u7ecf\\u9ed8\\u8ba4\\u88ab\\u5305\\u542b\\u3002<\\/p>\\r\\n\\r\\n

\\u5982\\u9700\\u4f7f\\u7528\\u961f\\u5217\\/\\u4f18\\u5148\\u961f\\u5217\\uff0c\\u60a8\\u53ef\\u4f7f\\u7528 datastructures-js\\/priority-queue@5.4.0<\\/a>\\uff0c datastructures-js\\/queue@4.2.3<\\/a> \\u4ee5\\u53ca datastructures-js\\/deque@1.0.4<\\/a>\\u3002<\\/p>\"],\"typescript\":[\"TypeScript\",\"

TypeScript 5.1.6<\\/p>\\r\\n\\r\\n

Compile Options: --alwaysStrict --strictBindCallApply --strictFunctionTypes --target ES2022<\\/p>\\r\\n\\r\\n

lodash.js<\\/a> \\u5e93\\u5df2\\u7ecf\\u9ed8\\u8ba4\\u88ab\\u5305\\u542b\\u3002<\\/p>\\r\\n\\r\\n

\\u5982\\u9700\\u4f7f\\u7528\\u961f\\u5217\\/\\u4f18\\u5148\\u961f\\u5217\\uff0c\\u60a8\\u53ef\\u4f7f\\u7528 datastructures-js\\/priority-queue@5.4.0<\\/a>\\uff0c datastructures-js\\/queue@4.2.3<\\/a> \\u4ee5\\u53ca datastructures-js\\/deque@1.0.4<\\/a>\\u3002<\\/p>\"]}", "book": null, "isSubscribed": false, "isDailyQuestion": false, "dailyRecordStatus": null, "editorType": "CKEDITOR", "ugcQuestionId": null, "style": "LEETCODE", "exampleTestcases": "(x) => x * 5\n[2]\n20\n50\n(x) => x**2\n[2]\n100\n50\n(x1, x2) => x1 * x2\n[2,4]\n30\n100", "__typename": "QuestionNode" } } }