{ "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 result = [];\n\nconst fn = (x) => x * 5;\n\nconst start = performance.now();\n\nconst log = (...argsArr) => {\n    const diff = Math.floor(performance.now() - start);\n    result.push({"time": diff, "returned": fn(...argsArr)});\n}\n     \nconst cancel = cancellable(log, [2], 20);\n\nconst maxT = Math.max(t, 50);\n          \nsetTimeout(cancel, cancelTimeMs);\n\nsetTimeout(() => {\n     console.log(result); // [{"time":20,"returned":10}]\n}, maxT + 15);\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;\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;\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

在经过 t 毫秒的延迟后,应该调用 fn 函数,并将 args 作为参数传递。除非t 毫秒的延迟过程中,在 cancelT 毫秒时调用了 cancelFn。并且在这种情况下,fn 函数不应该被调用。

\n\n

示例 1:

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

示例 2:

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

示例 3:

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

 

\n\n

提示:

\n\n\n", "isPaidOnly": false, "difficulty": "Easy", "likes": 4, "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}", "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\t\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\": \"2.7K\", \"totalSubmission\": \"3.3K\", \"totalAcceptedRaw\": 2672, \"totalSubmissionRaw\": 3325, \"acRate\": \"80.4%\"}", "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 16.13.2<\\/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.3.0<\\/a> \\u548c datastructures-js\\/queue@4.2.1<\\/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.3.0<\\/a> \\u548c datastructures-js\\/queue@4.2.1<\\/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" } } }