2776. 转换回调函数为 Promise 函数 🔒
2776. 转换回调函数为 Promise 函数 🔒
题目
Write a function that accepts another function fn
and converts the callback- based function into a promise-based function.
The function fn
takes a callback as its first argument, along with any additional arguments args
passed as separate inputs.
The promisify
function returns a new function that should return a promise. The promise should resolve with the argument passed as the first parameter of the callback when the callback is invoked without error, and reject with the error when the callback is called with an error as the second argument.
The following is an example of a function that could be passed into promisify
.
function sum(callback, a, b) {
if (a < 0 || b < 0) {
const err = Error('a and b must be positive');
callback(undefined, err);
} else {
callback(a + b);
}
}
This is the equivalent code based on promises:
async function sum(a, b) {
if (a < 0 || b < 0) {
throw Error('a and b must be positive');
} else {
return a + b;
}
}
Example 1:
Input:
fn = (callback, a, b, c) => { callback(a * b * c); }; args = [1, 2, 3];
Output:
Explanation:
const asyncFunc = promisify(fn); asyncFunc(1, 2, 3).then(console.log); // 6
fn is called with a callback as the first argument and args as the rest. The promise based version of fn resolves a value of 6 when called with (1, 2, 3).
Example 2:
Input:
fn = (callback, a, b, c) => { callback(a * b * c, 'Promise Rejected'); }; args = [4, 5, 6];
Output:
Explanation:
const asyncFunc = promisify(fn); asyncFunc(4, 5, 6).catch(console.log); // "Promise Rejected"
fn is called with a callback as the first argument and args as the rest. As the second argument, the callback accepts an error message, so when fn is called, the promise is rejected with a error message provided in the callback. Note that it did not matter what was passed as the first argument into the callback.
Constraints:
1 <= args.length <= 100
0 <= args[i] <= 10^4
题目大意
编写一个函数,接受另一个函数 fn
,并将基于回调函数的函数转换为基于 Promise 的函数。
promisify
函数接受一个函数 fn
,fn
将回调函数作为其第一个参数,并且还可以接受其他额外的参数。
promisify
返回一个新函数,新函数会返回一个 Promise 对象。当回调函数被成功调用时,新函数返回的 Promise 对象应该使用原始函数的结果进行解析;当回调函数被调用出现错误时,返回的 Promise 对象应该被拒绝并携带错误信息。最终返回的基于 Promise 的函数应该接受额外的参数作为输入。
以下是一个可以传递给 promisify
的函数示例:
function sum(callback, a, b) {
if (a < 0 || b < 0) {
const err = Error('a and b must be positive');
callback(undefined, err);
} else {
callback(a + b);
}
}
这是基于 Promise 的等效代码:
async function sum(a, b) {
if (a < 0 || b < 0) {
throw Error('a and b must be positive');
} else {
return a + b;
}
}
示例 1:
输入:
fn = (callback, a, b, c) => { return callback(a * b * c); }; args = [1, 2, 3];
输出:
解释:
const asyncFunc = promisify(fn); asyncFunc(1, 2, 3).then(console.log); // 6
fn 以回调函数作为第一个参数和 args 作为其余参数进行调用。当使用 (1, 2, 3) 调用时,基于 Promise 的 fn 将解析为值 6。
示例 2:
输入:
fn = (callback, a, b, c) => { callback(a * b * c, 'Promise Rejected'); }; args = [4, 5, 6];
输出:
解释:
const asyncFunc = promisify(fn); asyncFunc(4, 5, 6).catch(console.log); // "Promise Rejected"
fn 以回调函数作为第一个参数和 args 作为其余参数进行调用。在回调函数的第二个参数中,接受一个错误消息,因此当调用 fn 时,Promise 被拒绝并携带回调函数中提供的错误消息。请注意,不管将什么作为回调函数的第一个参数传递都无关紧要。
提示:
1 <= args.length <= 100
0 <= args[i] <= 10^4
解题思路
理解回调函数结构:
fn
接受回调函数callback
作为第一个参数,其余参数作为执行fn
的输入参数。- 回调函数的形式为
callback(result, error)
,如果error
不为空,则表示函数执行失败,否则表示成功。
包装为 Promise:
- 创建并返回一个新函数,该函数返回一个 Promise。
- 该函数使用
fn
进行调用,并传递一个自定义回调函数callback
以及除callback
以外的其他参数。
处理 Promise 解析和拒绝:
- 自定义
callback
检查回调函数的第二个参数error
。 - 如果
error
存在,则拒绝 Promise;否则,将第一个参数result
传递给resolve
,实现成功解析。
- 自定义
复杂度分析
- 时间复杂度:
O(1)
,创建和返回 Promise 的时间是常数级别。 - 空间复杂度:
O(1)
,仅创建一个 Promise 对象和回调函数,空间需求恒定。
代码
/**
* @param {Function} fn
* @return {Promise<any>}
*/
var promisify = function (fn) {};
return function (...args) {
return new Promise((resolve, reject) => {
const callback = (result, error) => {
if (error) {
reject(error);
} else {
resolve(result);
}
};
fn(callback, ...args);
});
};
}
/**
* const asyncFunc = promisify(callback => callback(42));
* asyncFunc().then(console.log); // 42
*/