We use cookies (including Google cookies) to personalize ads and analyze traffic. By continuing to use our site, you accept our Privacy Policy.

Convert Callback Based Function to Promise Based Function

Number: 2782

Difficulty: Medium

Paid? Yes

Companies: N/A


Problem Description

Given a callback-based function fn that receives a callback as its first argument (followed by any number of additional parameters), write a function promisify that converts fn into a promise-based version. The returned function should, when invoked, call the original fn with a callback that resolves the promise with the first parameter if no error is provided, or rejects the promise with the error provided as the second parameter if it exists.


Key Insights

  • Wrap the execution of fn inside a promise.
  • The callback passed to fn must analyze its arguments: if a second argument (error) exists, reject the promise; otherwise, resolve it.
  • The returned promisified function should accept the same non-callback parameters as fn, and internally pass them along with the callback.

Space and Time Complexity

Time Complexity: O(1) per function call since we are simply wrapping the call in a new promise. Space Complexity: O(1) aside from the space used by the promise object and local variables.


Solution

We use a higher-order function that returns a new function wrapping the original callback-based function call inside a promise. When the returned function is invoked, it:

  1. Creates and returns a new promise.
  2. Defines a callback that will check if an error argument exists (indicating rejection) or not (indicating resolution).
  3. Calls the original fn, passing the callback as the first argument and forwarding any additional arguments. This pattern cleanly converts callback-based APIs into promise-based ones, enabling modern asynchronous patterns like async/await.

Code Solutions

# Python solution using asyncio.Future to simulate promise-like behavior.
import asyncio

def promisify(fn):
    def wrapper(*args):
        loop = asyncio.get_event_loop()
        future = loop.create_future()
        
        # Define a callback to be passed to fn
        def callback(result, error=None):
            # If an error is provided, reject the future
            if error is not None:
                future.set_exception(Exception(error))
            else:
                future.set_result(result)
        
        # Call the original function with callback as the first argument
        fn(callback, *args)
        return future
    
    return wrapper

# Example usage:
def sum_callback(callback, a, b):
    if a < 0 or b < 0:
        callback(None, "a and b must be positive")
    else:
        callback(a + b)

# To test, run the coroutine in the event loop:
async def main():
    async_sum = promisify(sum_callback)
    try:
        result = await async_sum(1, 2)
        print("Result:", result)  # Expected: 3
    except Exception as e:
        print("Error:", e)

# Uncomment below if running as a standalone script:
# asyncio.run(main())
← Back to All Questions