Ways to convert a callback-based function into a promise without losing the returned value

After being given access to this API:

function doSomeWork(callbacks : {
    success ?: (result : SuccessCallbackResult) => void,
    fail ?: (result : FailCallbackResult) => void,
    complete ?: (result : CompleteCallbackResult) => void
}) : Task

I managed to create a function that wraps it and returns a Promise:

function doSomeWorkAsync() : Promise<SuccessCallbackResult> {
    return new Promise((resolve, reject) => {
        const callbacks = {
            success: resolve,
            fail: reject,
        };

        doSomeWork(callbacks);
    });
}

However, the issue is that by doing this I lose access to the Task returned by doSomeWork.

Is there a way for me to modify the wrapper so that I can obtain both a Promise and a Task? Perhaps something along these lines:

function doSomeWorkAsync() : [Promise<SuccessCallbackResult>, Task] {
    // implementation
}

Furthermore, it is crucial that the Task is returned synchronously since it may be required to perform actions like .abort().

Answer №1

Is there a way to encapsulate the API so that I can access both a Promise and a Task?

Absolutely, by utilizing the synchronous execution of the new Promise callback:

function performAsyncWork(): [Promise<SuccessCallbackResult>, Task] {
    let task;
    const promise = new Promise((resolve, reject) => {
        task = executeWork({ resolve, reject });
    });
    return [promise, task];
}

(In TypeScript, you may need to add a task as Task assertion to inform the compiler that task has been assigned before being used)

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Where do I find the resultant value following the completion of a video production through editly?

Hey there, I have a quick question... I was following the instructions in the README for editly, and I successfully created videos by calling editly like this: // creating video editly(editSpec) .catch(console.error); The only issue is that I am using Ex ...

What is the best way to locate a div element with a specific style?

What is the method to locate a div element by its style? Upon inspecting the source code in IE6, here is what I find: ...an><div id="lga" style="height:231px;margin-top:-22px"><img alt="Google"... How can this be achieved using JavaScript? ...

The value of msg.member is empty following the messageReactionAdd event

Whenever someone reacts on my server, it triggers the messageReactionAdd event. However, I am encountering difficulty in retrieving the member object of the author of a message that someone reacted to: module.exports = async (client, messageReaction, user) ...

Establishing a default v-on event for a Vue component

Within my custom 'text-input' components, I include some default markup and an 'input' element. An effective method for passing the value of the 'text-input' to its parent is by emitting an event when the value changes. To h ...

Sharing data between the main component and the sidebar in React-Router

Currently working with Meteor in combination with React-Router, and this is the code I'm dealing with: Routes.jsx: Meteor.startup(() => { render( <Router history={browserHistory}> <Route path='/' component={App}> ...

Passing a value through jQuery Ajax when selecting an option (onchange) to store in a PHP variable on the same page without

How can I retrieve the selected value using PHP and update a specific div element with it? <div id="test"> <?php if (isset($_POST['sweets'])) { ob_clean(); echo $_POST['sweets']; exit; } ?> ...

Executing MongoDB collection operations with array filtering

I am looking to count records based on tags and filter them before including in specific groups // data in database {tags: ['video', 'Alex'], ... }, {tags: ['video', 'John'], ... }, {tags: ['video', 'J ...

Spinning a line in three.js along the circumference of a circle

let lineGeo = new THREE.Geometry(); let lineMat = new THREE.LineBasicMaterial({ color: 0x000000 }); lineGeo.vertices.push( new THREE.Vector3(0, 0, 0), new THREE.Vector3(0, 10, 0), ); let myLine = new THREE.Line(lineGeo, lineMat); scene.add(myLi ...

Difficulty transmitting Heroku environment variable to Angular CLI application using Node.js

Currently, I am tackling a project that requires passing a stripe key as JSON within Angular. I've stored the key in Heroku config vars and have been attempting to pass that value through the Node.js backend to Angular using the process.env.STRIPE_KE ...

Incorporating Framer Motion into traditional React class components (non-functional approach)

I'm encountering an issue with a simple animation using Framer Motion that functions correctly in a functional component, but fails to work in a class component. I am new to Framer Motion and here is my react code => import {motion} from 'fr ...

Is there a way for me to display a gif similar to 9GAG on my

I'm looking to implement a feature on my website that allows me to pause and play a gif, similar to the functionality on 9gag. Can anyone provide guidance on how I can achieve this? I understand that I need to use both .jpg and .gif files, but my at ...

What are the steps to effectively create a cascade of Q promises?

Consider the following scenario as an illustration: I have 3 URLs stored in an array called "urls" The "require" function returns a promise that performs an $http call The code provided is functional, but it doesn't meet my desired outcome since th ...

What is the best way to define a category in order to utilize a saved string as a variable for referencing it?

An object named CONFIG holds the following information: export const CONFIG = { buttonDestinations: { detailedStats: `detailedStats`, mealPlans: `mealPlans`, products: `products` }, buttonTexts: { detailedStats: ...

Preventing autoscrolling in Ionic's dual side menu template when additional content is added

Could anyone kindly assist me in figuring out why the autoscrolling of the content is not functioning correctly? Whenever the button on the header is clicked, a new message will be included in the main content. However, once the number of lines exceeds wha ...

What is the reason behind the file not found error encountered when running Deno with the command "echo hello"?

Exploring Deno's standard library, I encountered an issue with Deno.run - a function designed to create a new subprocess. Here is the example provided in the documentation: const p = Deno.run({ cmd: ["echo", "hello"], }); When I attempt to run ...

Try out the Jquery Chosen plugin, which allows you to select multiple instances of the same

I am currently using the chosen plugin to create multiple select input fields. You can view an example of this in action by following this link: By default, the plugin disables an option if it has already been selected. For instance, in the provided examp ...

Utilize Vue.js to take screenshots on your device

After following the tutorial at https://www.digitalocean.com/community/tutorials/vuejs-screenshot-ui, I was able to successfully capture a screenshot with Vue.js. However, it seems that the dimensions of the screenshot are not quite right. Issue: The cap ...

Utilizing AngularJS to include information into JSON-LD

As a newcomer to AngularJS, I find myself stuck in one of my projects. My goal is to convert the user-entered data in a form into the format: << "schema:data" >> and then push and display it within the @graph of the json-ld. Here are my HTML an ...

Sending data from the View to the Controller in a Razor MVC3 application involves passing a model along with

Within my view, there's a form representing my View model with multiple fields. I aim to generate a list of links for pagination purposes that will not only redirect to a specific page but also send the input data from the form along with it. The Java ...

Ways to efficiently manage session control without repeating it in each route

I'm currently working on a Node.js application using express. I've been checking the session in every route, but now I'm looking for a way to separate this check from my routes. Any suggestions? Below is an example of one of my routes: app ...