Tips for preventing the extraction of resolve from promises and initiating a process before a callback

There is a common pattern I frequently find myself using:

const foo = () => {
    const _resolve;
    const promise = new Promise(resolve => _resolve = resolve);
    myAsyncCall(_resolve);
    return (dataWeDontHaveYet) => promise.then(cb => cb(dataWeDontHaveYet));
}
const finalData = async2(foo());

function async2(cb) {
    ... async stuff ...
    return cb(dataWeDidntHaveBefore);
}

function myAsyncCall(cb) { return cb(somePrimitive); }

I often need to start an async call immediately, but process the resolved data that I do not have yet.

This resembles a queue in some ways.

I am questioning whether using promises for this purpose is ideal. While I have used similar code before, I am struggling to convert a stream into a generator effectively at the moment.

EDIT: For a more specific issue related to this problem, see my question posted at How to convert a stream into a generator without leaking resolve from a promise

Answer №1

The code snippet you provided seems a bit unclear, so I'll do my best to provide an alternative solution.

To handle async data, you can use either Promises or callbacks. You can chain them together and return the beginning of the Promise.

For example, if your myAsyncCall() function returns a Promise, you can simply do:

return myAsyncCall();

This will return a Promise that resolves once myAsyncCall() is completed. If you need to transform the data, you can chain multiple then() calls:

return myAsyncCall().then(data => transform(data));

This sequence ensures that myAsyncCall() is executed first, followed by any transformations, with subsequent then() calls receiving the latest data.

If myAsyncCall() uses a callback instead, you can convert it to return a Promise:

return new Promise((resolve) => {
  myAsyncCall(data => resolve(data));
});

This approach allows myAsyncCall() to resolve first, passing its data to a Promise for further processing.


Based on your recent updates, it appears you want to chain callbacks and Promises effectively in your code.

Let's start with traditional callback chaining:

const a = (start, cb) => cb(start);
const b = (input, cb) => cb(input + 5);

a(1, result => 
  b(result, newResult => 
    console.log(newResult)
  )
);

In this scenario, functions are nested within each other, which can get messy. Some developers prefer breaking it down into separate functions:

const a = (start, cb) => cb(start);
const b = (input, cb) => cb(input + 5);

const onA = result => b(result, onB);
const onB = result => console.log(result);

a(1, onA);

When using Promises, chaining them is done through the then() method. Here's how you can achieve the same functionality with Promises:

const a = start => Promise.resolve(start);
const b = input => Promise.resolve(input + 5);

a(1).then(b).then(result => console.log(result));

If you need to mix callbacks and Promises, one approach is to combine them directly:

const a = start => Promise.resolve(start);
const b = (input, cb) => cb(input + 5);

a(1).then(result => b(result, result => console.log(result)));

To simplify the process, you can create a "promisify" function that converts a callback function to a Promise. Here's a basic implementation:

const promisify = func => (...args) => new Promise(resolve => {
  const cb = result => resolve(result);
  func.apply(func, args.concat(cb));
});

const a = (start, cb) => cb(start);
const b = (input, cb) => cb(input + 5);

const aPromisified = promisify(a);
const bPromisified = promisify(b);

aPromisified(1)
 .then(bPromisified)
 .then(result => console.log(result));

This "promisify" function simplifies the conversion of callbacks to Promises, making it easier to work with mixed approaches.

If you require a more advanced "promisify" function that handles callbacks with error handling, you can modify the function as follows:

const promisify = (func, withErr = false) => (...args) => new Promise((resolve, reject) => {
  const handler = (err, result) => {
    if(withErr) {
     err ? reject(err) : resolve(result);
    } else {
     resolve(err);
    }
  }
  
  func.apply(func, args.concat(handler));
});

const aCallback = (start, cb) => cb(start);
const bCallback = (input, cb) => cb(input === 3 && 'cannot be 3', input + 5);

const a = promisify(aCallback);
const b = promisify(bCallback, true);

a(1).then(b).then(r => console.log(r));
a(3).then(b).catch(err => console.error(err));

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

Navigating through elements in the hidden shadow DOM

Can elements within the Shadow DOM be accessed using python-selenium? For example: There is an input field with type="date": <input type="date" name="bday"> I want to click on the date picker button located on the right and select a ...

Is there a way to capture all ajax responses?

Is it possible to capture all responses from an ajax request, regardless of the library being used such as jQuery, prototype, or just the vanilla XMLHttpRequest object? I am looking for a way to append to any existing handler without removing it. Thank y ...

What's the alternative now that Observable `of` is no longer supported?

I have a situation where I possess an access token, and if it is present, then I will return it as an observable of type string: if (this.accessToken){ return of(this.accessToken); } However, I recently realized that the of method has been deprecated w ...

Utilize the Spotify API to discover tracks by including the album title and artist's name in the search

Currently working on a project that involves searching for a music track on Spotify. The idea is to input the track name in the text area and generate a list of matching Track IDs along with Artist Names, Album Names, and Artwork. I have made some progress ...

Tips for utilizing both the Element Selector and Class Selector in Jquery

I am working with a simple table that has TDs assigned either the 'PLUS' or 'MINUS' class. My goal is to use jQuery to implement functionality for collapsing all or expanding all. When the Expand All button is clicked, I need to chang ...

What could be causing these transformed canvases to not display fully in Chrome at specific resolutions?

fiddle: https://jsfiddle.net/f8hscrd0/66/ html: <body> <div id="canvas_div"> </div> </body> js: let colors = [ ['#000','#00F','#0F0'], ['#0FF','#F00','#F0F&a ...

JavaScript - Retrieving the variable's name

Whenever I invoke a function in JavaScript with a variable, like this: CheckFunction(MyVariable); CheckFucntion(MyVariable2); Suppose I have a function that checks if the input is a number: function CheckFunction(SOURCE){ //THE CODE ITSELF }; I want to ...

Padding-left in InfoBox

Currently, I am in the process of developing a map using Google Maps API3 along with the InfoBox extension available at this link I have successfully implemented an overall padding to the Infobox using the following code snippet: var infoOptions = { disa ...

What is the best way to attach functions to specific jQuery objects and exclude others?

Imagine having an unordered list <ul>: <ul class="products"> ... </ul> You want to use jQuery to select it and then add custom functions to that specific object. For instance, you wish to include an addProduct(productData) function ...

Guide to showcasing object characteristics inside an object in Angular2

My USAFacts object contains properties like StateName, as well as objects like State-Bird which hold information about the state bird. If written in JSON, a record of USAFacts would appear as follows: {"StateName": "PA", "State-Bird": [ { "Name": "Ruffed ...

NextJS: Retrieve the information in its initial state

Is there a way to retrieve the original format of a value? For example: The values in my textarea are: Name: Your Name Email: <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="f980968c8b9c94989095b994989095d79a9694">[email ...

Learn the process of creating test cases using `ava` for the following code snippet

const TimeToEvent = minutes => { const oneMinute = 1; const minutesInAnHour = 60; if (minutes <= oneMinute) { return "in just 1 minute"; } if (minutes < minutesInOneHour) { return "in mere&quo ...

Unable to load routes from ./app.js in the file ./src/routes/index.js

Just dipping my toes into the world of nodejs. I recently moved all my routes from app.js to a separate file located at PROJECT_DIR/src/routes/index.js. However, when I try to open the page in my browser, it displays "Cannot GET /wines". Below are snippets ...

The modal appears on the screen prior to the content being shown

While attempting to render a bootstrap modal with content from a REST call, I am encountering an issue where the modal appears before the content has finished populating. The modal is triggered by a button click event. If I click the button again after wa ...

Updating by clicking with auto-prediction feature

I have implemented an autosuggestion feature to display results from a database table while typing in an HTML field, and I am looking to utilize JavaScript to post another value from the same row where the autosuggested values are stored. https://i.stack. ...

Ways to Retrieve the Index of Elements in the DOM Array Generated by the querySelectorAll() Function in JavaScript

const items = document.querySelectoAll('.class') console.log(items) // Array with 15 elements (This array contains a total of 15 elements) ...

A guide to swapping text in a jQuery DOM component

In order to construct HTML from a jQuery ajax response, I prefer not to nest unsightly strings in javascript and avoid using templating scripts like mustache. Instead, I decided to utilize a template HTML with display: none as shown below: <div id="mes ...

How can I extract the JSON value as a string?

I have a scenario where I define two objects. The first object, BOB, has properties "name" with a value of "bob" and "height" with a value of 185. var BOB = { "name": "bob", "height": 185 }; The second object, PROPS, references the height property from ...

Create a personalized Command Line Interface for the installation of npm dependencies

I am looking to develop a Node CLI tool that can generate new projects utilizing Node, Typescript, Jest, Express, and TSLint. The goal is for this CLI to create a project folder, install dependencies, and execute the necessary commands such as npm i, tsc - ...

Encountered an issue with the ProgressPlugin: TypeError - Unable to access property 'tap' of an undefined element

Encountering a Problem with npm run build Here's the issue at hand Compiling client E:\ui\sheraspace_ui\node_modules\webpack\lib\ProgressPlugin.js:223 compilation.hooks.addEntry.tap("ProgressPlugin", entryAdd ...