Is it possible for the second .then to execute before the first one in a Promise chain? Mind-blowing!

I am currently working on creating a new File object from blob data within a .then structure. However, I have encountered an issue where the second .then function runs before the first one finishes, resulting in the file object not being fully filled yet.

Is this normal behavior? Should I consider making the first .then function an async function to ensure that the second one is only called after the file object has been properly populated?


let output = {file: {}, file_infos: {}},
    image = FileAPI.Image(src_file);
await Promise.all(Object.keys(parameters).map(async (parameter_name) => {
  try {
    image = await FileMethods[parameter_name](image, parameters[parameter_name]);
    return image;
  }
  catch(err) {
    console.log(err);
  };
}))
.then((output_image) => {
  output_image[0].toBlob((blob) => {
    output.file = new File([blob], src_file.name); // This needs to be completed before moving to step 2
    console.log('step1');
  });
})
.then(() => {
  console.log('step2');
  FileAPI.getInfo(output.file, (err/**String*/, infos/**Object*/) => {
    if( !err ){
      output.file_infos = infos;
    } else {
      console.log("This error occurred because output.file was not fully filled yet");
    }
  })
});
// console.log(output);
return output;

The console output displays:

step2
This error occurred because output.file was not fully filled yet
step1

Thank you for your assistance :)

Answer №1

Ensure that the two asynchronous functions within the .then blocks are "Promisified" since they do not return a Promise. Also, considering the use of async/await, it is advisable to avoid chaining promises with .then.

const image = FileAPI.Image(src_file);
const output_image = await Promise.all(Object.keys(parameters).map(async(parameter_name) => {
    try {
        image = await FileMethods[parameter_name](image, parameters[parameter_name]);
        return image;
    } catch (err) {
        console.log(err);
    };
}));
const file = await new Promise((resolve, reject) => output_image[0].toBlob((blob) => 
    resolve(new File([blob], src_file.name))
));
const file_infos = await new Promise((resolve, reject) => FileAPI.getInfo(file, (err, file_infos) => {
    if (!err) {
        resolve(file_infos);
    } else {
        reject("this is triggered because output.file isn't filled yet");
    }
));
return {file, file_infos};

Regarding the section:

const output_image = await Promise.all(Object.keys(parameters).map(async(parameter_name) => {
    try {
        image = await FileMethods[parameter_name](image, parameters[parameter_name]);
        return image;
    } catch (err) {
        console.log(err);
    };
}));

You could simplify it by returning directly the promise in the .map without using async/await like this:

const output_image = await Promise.all(Object.keys(parameters).map((parameter_name) => 
    FileMethods[parameter_name](image, parameters[parameter_name]);
));

Another approach could be:

const output_image = await Promise.all(Object.entries(parameters).map((p_name, p_value) =>
    FileMethods[p_name](image, p_value)
));

If you prefer using Promise .then chains and avoiding async/await:

const image = FileAPI.Image(src_file);
return Promise.all(Object.keys(parameters).map(parameter_name => FileMethods[parameter_name](image, parameters[parameter_name])))
.then(output_image => new Promise((resolve, reject) => output_image[0].toBlob((blob) => 
    resolve(new File([blob], src_file.name))
)))
.then(file => new Promise((resolve, reject) => FileAPI.getInfo(file, (err, file_infos) => {
    if (!err) {
        resolve({file, file_infos});
    } else {
        reject("this is triggered because output.file isn't filled yet");
    }
)));

Answer №2

.toBlob() executes quickly due to its use of the asynchronous callback approach.

If you require a promise that resolves upon completion of the task, consider this implementation:

.then((output_image) => {
    return new Promise((resolve, reject) => {
      output_image[0].toBlob((blob) => {
        output.file = new File([blob], src_file.name); // This must be completed before proceeding to step 2
        console.log('step1');
        resolve();
      });
    });
  })

Answer №3

toBlob is likely running asynchronously. Adjust the initial .then to the following:

.then((output_image) => {
  return new Promise((resolve) => output_image[0].toBlob((blob) => {
    output.file = new File([blob], src_file.name); // This must be completed before proceeding to step2
    console.log('step1');
    resolve();
  }));
})

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

Create a new division directly underneath the bootstrap column

Imagine having a bootstrap table like this: https://i.sstatic.net/kXHiP.jpg Now, if you want to click on a column and open a div with more details below it, is it achievable with CSS or JavaScript? https://i.sstatic.net/HIfkK.jpg I tried using the Metr ...

During the click event, two distinct $.ajax requests interfere and cancel each other out

Here's a dilemma I'm facing: On my webpage, I have implemented two different click events. The first one opens a modal displaying a larger image when you click on a thumbnail picture (similar to Instagram on PC - I created an Instagram clone for ...

Having issues with array.push functionality in JavaScript

let chatConversations = new Array(); jQuery('.CChatWindow').each(function(){ if (jQuery(this).is(":visible") && jQuery(this).attr("data-conversationid") != 0) { alert(jQuery(this).attr("data-conversationid")); // returns 1 and ...

Efficient Routing with React Router 4: Embracing Code Splitting and Component Remount

Here is the code snippet in question: import React from 'react' import Loadable from 'react-loadable' import { Route } from 'react-router-dom' class App extends React.Component { state = { kappa: false } ...

establish the reliance on field w

I want to create a dependency between two fields. The selectbox contains a list of options. If the first or fifth option is selected in the dropdownbox, apply the class "selectboxlist". Then I would like to set the value '-1' in the second ...

Creating a many-to-many relationship in Sequelize using a join table to insert data

I recently set up two models in sequelize with a many-to-many relationship. While Sequelize successfully created the join table, I am facing difficulties when trying to insert data into it. Despite going through the documentation section on associations ...

Merging values of different keys in a .json file

Check out my json file below: { "foo": "https://3a1821d0.ngrok.io/api/foo", "bar": "https://3a1821d0.ngrok.io/api/bar", } I am interested in changing the key 3a1821d0 to a different variable within the json structure, like so: { "some_variab ...

React Native: A guide to triggering a modal or action sheet when a button tab is clicked using Wix React Native navigation

Is it possible to trigger a modal or actionsheet by clicking on a specific bottom tab in a tab-based application using wix react native v2 navigation? These are the current packages and versions I am working with: react-native : "0.59.8" react : "16.8. ...

Ensure redirect is delayed until async data is fetched

Having come from the Angular world, I found it really easy and convenient to resolve data for routes. However, now that I'm using React, I'm unsure about how to achieve the same functionality. I would like to add an async data loader for my rout ...

Display all active services in a new list item using AngularJS Ionic's ng-repeat directive

I've been working on a shopping cart feature for my Ionic app and everything is coming together nicely, except for the running itemized total. By default, the items in my array are set to active:false and when selected, they switch to active:true and ...

One benefit of using a self-invoking function within a function declaration

What are the benefits of defining a function like this: obj = { func: function(){return function func(){return this.something;};}() } Anecdote: I was searching for a solution on how to rotate a Three.js Vector3 by a specific angle around an axis and stumb ...

Ways to conceal the contents of an HTML element

I recently applied a background image to my "a" tag, but now I'm looking to hide only the HTML content within the tag. It's important that the background image and href address remain visible. Any suggestions on how to achieve this? Thank you in ...

What could be causing my for loop to not function properly within the ngOnInit lifecycle hook?

I am attempting to create a nested loop structure in order to access an array that is inside an object within an array of objects, and then store this data into a new array. My issue arises as the first loop executes successfully but the second one does no ...

Modify one of the items in the array without changing its original state

Within the React component's state, I have a property named formErrors which consists of an array of objects that dynamically changes. Here is the structure: [ {fieldName: 'title', valid: false}, {fieldName: 'description', va ...

A guide to troubleshoot and resolve the 500 (Internal Server Error) encountered during an Ajax post request in Laravel

I am facing an issue in my project where I am trying to store data into a database using ajax. However, when I submit the post request, I get an error (500 Internal Server Error). I have tried searching on Google multiple times but the issue remains unreso ...

Exploring Vuetify's TreeView for Dynamic Data Management

I am looking for a way to utilize the v-treeview component from Vuetify in order to construct a hierarchical list of items. This list could potentially have multiple layers, ranging from 10 to 100 levels deep, each containing around 100 items. How can I tr ...

Rendering React Js component occurs just once following a state update

My journey with ReactJS is just beginning, and I'm facing an unusual issue which might be due to my unconventional implementation approach. Previously, everything was working smoothly. However, when I tried to introduce new features, things started g ...

preventing sliding in a specific angle within the angularjs ionic framework

I am completely new to angularjs and embarking on my very first app creation journey with the ionic framework. The initial step I took was to generate an ionic app using this command: $ ionic start myApp sidemenu The creation of the app went smoothly, co ...

Export default does not actually yield a function; rather, it returns an object

I recently developed a function that is responsible for importing a script from a specified source, calling its exported function, and handling the returned result. To simplify things, I have streamlined the code to focus solely on returning the result. co ...

Issues with the LIKE operator

I'm currently developing a compact mobile web application. One of the challenges I am facing involves a SQL query that includes a LIKE clause. Here is an example: SELECT from posts WHERE (title LIKE '%car%') or (content LIKE '%car%&apo ...