Promise .then() chains: second .then run before the first?? o.0

I'm trying to create a new File object from blob data in a .then structure, and after in the second .then, read info of this file.

But the second then run before the first end, so the file object isn't filled yet.

Is that a normal behavior? Should I make an async function, called in the first then to ensure the second one is strictly called after?

      let output = {file: {}, file_infos: {}},
          image = FileAPI.Image(src_file);
      await Promise.all(Object.keys(parameters).map(async (parameter_name) => { // Pass file threw all modifiers (resizing, rotation, overlaying)
        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); // Need this to be fullfilled before step2
          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 is triggered because output.file isn't filled yet");
          }
        })
      });
      // console.log(output);
      return output;

console shows me:

step2 this is triggered because output.file isn't filled yet step1

Thanks for helps :)


The two asynchronous functions in the two .then's do not return a Promise, so first they need to be "Promisified", also, since you're already using async/await don't use a promise .then chain

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};

A note about

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're essentially doing return await FileMethods[parameter_name](image, parameters[parameter_name]) - so, you really don't need in this case an async/await pattern, just return the Promise in the .map

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

Or, even nicer (in my opinion)

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

Alternatively, to use Promise .then chains and no 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");
    }
)));

Promise .then() chains: second .then run before the , The two asynchronous functions in the two .then's do not return a Promise, so first they need to be "Promisified", also, since you're already using async/await  Here the first .then shows 1 and returns new Promise(…) in the line (*).After one second it resolves, and the result (the argument of resolve, here it’s result * 2) is passed on to handler of the second .then.


.toBlob() returns instantly because it uses the asynchronous callback pattern.

What you want is to return a promise that resolves when the work is done. So you could do something like this:

.then((output_image) => {
    return new Promise((res, rej) => {
      output_image[0].toBlob((blob) => {
        output.file = new File([blob], src_file.name); // Need this to be fullfilled before step2
        console.log('step1');
        res();
      });
    });
  })

Using Promises, Callbacks added with then() even after the success or failure of the asynchronous operation, will be called, as above. This second promise ( promise2 ) represents the completion not just doSomething() .then(function(result) { return doom earlier, compared to only once at the end of the promise chain: If one or both arguments are omitted or are provided non-functions, then then will be missing the handler(s), but will not generate any errors. If the Promise that then is called on adopts a state (fulfillment or rejection) for which then has no handler, a new Promise is created with no additional handlers, simply adopting the final state of the original Promise on which then was called.


toBlob is probably asynchronous. Change the first .then to this:

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

Graceful asynchronous programming with Promises, If they all fulfil, the chained .then() block's First of all, the second promise we Second, we have added the return keyword before the fetch() call. The effect this has is to run the entire chain and then run the createObjectURL(values[0]); let  A Promise is an object representing the eventual completion or failure of an asynchronous operation. Since most people are consumers of already-created promises, this guide will explain consumption of returned promises before explaining how to create them.


Promises chaining, promise . then ( f1 ) . catch ( f2 ) ; To insert a few words of code, use the <code> tag, for several lines so what they reason for first 2 values which is JSON ? lesson, where it is said that .then() got two arguments. the result, and second argument runs when promise is  JavaScript Promises in Sixteen Minutes ever move on to the second thing until the first thing has run its course — then we can’t possibly have all of the smooth, interactive experiences


JavaScript for Data Science, Plan B is to chain the promises together to ensure that each executes only after the last let total_size = 0 new Promise((resolve, reject) => { fs.stat(′jane-eyre.​txt′).then((jeStats) Before we begin, we will want the name of the directory to are:′, process.argv) and run it like this: $ node src/promises/echo.js first second. The best way to do this is by making a reusable function for this. This can even be done with just one line of code using reduce:. function chainPromises(list) { return list.reduce((chain, func) => chain ? chain.then(func) : func(), null); }


25. Promises for asynchronous programming, then() always returns a Promise, which enables you to chain method calls: Let's look at a first example, to give you a taste of what working with Promises is like. Second, you can handle the errors of both readFilePromisified() and the access the eventual value via [0] (as in line A), you use method then() and a callback. You can also chain thens to run async actions in sequence. When you return something from a then() callback, it's a bit magic. If you return a value, the next then() is called with that value. However, if you return something promise-like, the next then() waits on it, and is only called when that promise settles (succeeds/fails). For example: