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

When I shift a JavaScript function from inline code to a separate JS file, I encounter the error message "function is not defined"

I am struggling to get a simple task done: <!DOCTYPE html> <html lang="en"> <head> </head> <body> <script src="js/test.js" type="text/js"></script> <button onclick="test()" type="submit">Test</button> ...

Invoke two functions simultaneously on a single Onchange event

Can someone help me understand how to trigger two functions by changing the value of a specific dropdown list using the "OnChange" event in Ajax? Note: The system typically only displays the output of the showhistory() function. Here is my existing code: ...

Customize date filtering in KendoUI grid

I am trying to modify the date format in the filter of my kendo grid. For example, I would like to change 1/30/2015 to Jan 30, 2015 I have successfully changed the date format for Start Date field: "StartDate", title: " ...

Click event recursion occurs due to the use of $.post

I have a collection of product rows available for customers to select from. Each row is designated with the class "product-line". Upon clicking on a row, I aim to visually indicate its selection status by toggling the "product-checked" class, and subsequen ...

Issue with Mjpg paparazzo.js functionality not functioning as expected

I am currently exploring alternative methods to view my security cameras without relying on browser support for mjpg streaming. I have come across Paparazzo.js, which appears to be a promising solution that I want to experiment with: https://github.com/rod ...

Prevent the selection of a dropdown option in AngularJS once it has already

var demoApp = angular.module('myApp', []); demoApp.controller('QaController', function($scope, $http) { $scope.loopData = [{}, {}]; $scope.questions = { model: null, availableOptions: [ {id: '1& ...

Customizing the appearance of a JavaScript countdown timer's output on an individual basis

I am currently working on customizing the appearance of a JavaScript date counter. My goal is to style the days, hours, minutes, and seconds individually. Ideally, I want each unit to be right-aligned within its own div, with specific left and top absolute ...

Creating interactive web pages for scheduling tasks

I'm struggling with how to implement this concept. Imagine I have a School website that features a schedule page for 30 upcoming courses. When a course is clicked, it should lead to a new page displaying specific information about that course (such a ...

Utilizing an array to pass a series of items to a function parameter

I am currently working on an Angular project that involves a controller and service. In this setup, the controller sends data and an endpoint to the service. As of now, the service handles the http request. However, I am in the process of refactoring my ...

The click event fails to trigger while trying to parse external HTML

Currently, I am working on a project that requires me to load HTML from an external file and insert it into an existing div element. Although the process is successful overall, I have encountered an issue where the .click() events do not trigger when click ...

What is causing my radio button event to activate when a separate radio button is selected?

I have implemented the code below to display "pers" and hide "bus," and vice versa. JQuery: $('input[name="perorbus"]').click(function() { if ($(this).attr('id') == 'bus') { $('#showbus&apo ...

When the number of selected students exceeds zero, activate the collapsing feature in React

When the number of students exceeds zero, the collapse should automatically open and the text in Typography (viewStudentList) will display 'Close'. On the other hand, if the student count is zero, the collapse should be closed and the text on Typ ...

Is it possible to upload files without using AJAX and instead through synchronous drag-and-drop functionality in the foreground?

Currently, my website has a standard <input type="file"> file upload feature that sends data to the backend upon form submission. I am looking to enhance the functionality of the form by allowing users to drag and drop files from anywhere within the ...

Using AJAX and React to handle RESTful requests

Hello there, I am attempting to utilize a web service in React but am encountering issues with the AJAX function. I'm unsure if my code is working as expected. Here is a snippet of my code: prox= {"email":email, "password": password}; //tag comment $ ...

Using ThreeJS to load and display several meshes from a .json 3D file

I downloaded a .json file from an online 3D editor and now I'm facing an issue while trying to load and create 20 instances of it, similar to this example. Sadly, my code seems to be flawed as all 20 instances are behaving as if they are the same obje ...

The table fails to refresh after adding, modifying, or removing a row

Incorporating ReactJs with Material-UI, I am working on displaying a table of Car components where the display does not update after any Create, Edit, or Delete action has been performed. Below is the structure: class MainCar extends React.Component { c ...

Why does the for loop function correctly with console.log but not with innerHTML?

Hello! I'm completely new to JavaScript, so please excuse any oversight... Below is the code that runs when a button on the page is clicked: function getNumbers() { var firstValue = document.getElementById("time_one").value; var ...

Learn the steps to invoke a JavaScript function from a <td> element within an ng-repeat loop

How can I call an Angular function inside ng-repeat td and replace the value from the function with the value in the td element? The code snippet provided below is not functioning as expected. Instead of getting the date, the same getCSTDateTime function i ...

What is the best way to trigger a modal to appear when dynamically generated items are clicked?

My objective is to retrieve specific data from the server and present it in a list format on my webpage. The list displays correctly, but I want users to be able to view additional details for each list item by clicking on it, triggering a modal popup. How ...

React filtering displaying array elements that appear single time

I've been working on this React code to filter and search items based on user input. The issue I'm facing is that when I delete the text input and try again, the filtered items disappear and don't show up unless I reload the page. I'm c ...