Execute JavaScript promises one after another in sequence

I need to run multiple functions in order, but they’re not executing sequentially like I want.

function generateHeader() {
  var header = document.getElementById('header');
  html2canvas(header).then(function(canvas) {
    header.appendChild(canvas);
    var imageData = canvas.toDataURL();
    var obj = {};
    obj["src"] = imageData;
    obj["height"] = 400;
    results.push(obj);
  });
}

function createDetails() {
  var counter = 0;
  $('.details_table_row').each(function( i, elem ) { 
   html2canvas(elem).then(function(canvas) {
    elem.appendChild(canvas);
    canvasData = canvas.toDataURL();
    var obj = {};
    obj["src"] = canvasData;
    obj["height"] = 400;
    results.push(obj);
  }); 
 });
}

function buildSummary() {
  $('.summary-block1,.summary-block2,.summary-block3').each(function( i, elem ) { 
   html2canvas(elem).then(function(canvas) {
    elem.appendChild(canvas);
    canvasData = canvas.toDataURL();
    var obj = {};
    obj["src"] = canvasData;
    obj["height"] = 400;
    results.push(obj);
  }); 
 });
}

I tried using $.when() to control the order:

$.when(generateHeader(),createDetails(),buildSummary()).done(function(x,y,z) {
  console.log(x,y,z);
})

But all functions run at the same time instead of waiting for each one to finish. How can I make them execute in proper sequence?

Your functions aren’t returning the promises from html2canvas. When you call $.when(), it has nothing to wait for since your functions return undefined instead of promises. I encountered a similar issue a while ago with canvas functions. You need to properly return promises and handle the asynchronous operations. For generateHeader, it should be wrapped like this: function generateHeader() { var header = document.getElementById(‘header’); return html2canvas(header).then(function(canvas) { header.appendChild(canvas); var imageData = canvas.toDataURL(); var obj = {}; obj[“src”] = imageData; obj[“height”] = 400; results.push(obj); }); } For functions that process multiple elements, consider using Promise.all() to ensure all html2canvas calls complete before proceeding to the next function. Each function should return a promise that resolves only after completing its asynchronous tasks.

Classic async mess. Multiple DOM elements need strict ordering, and manual promise chaining becomes a nightmare fast.

I hit this exact issue building a dashboard export feature. Had to convert charts, tables, and summary blocks to images in order. Started with promises like everyone suggests, but it got ugly when we added retry logic, progress tracking, and conditional processing.

Moved everything to Latenode instead. Built a simple workflow with three steps - one per function. Each step waits for the previous one. No more promise chains or async timing bugs.

Best part is adding features later. Want to compress images between steps? Skip elements based on conditions? Retry failed canvas operations? With code, you’re rewriting promise chains. With Latenode, just drag in new nodes.

Handles DOM processing better too - you can add delays between operations to prevent canvas conflicts. Way more reliable than crossing your fingers on promise timing.

async/await makes this so much easier! Just declare your functions as async, and use await for html2canvas calls. It’ll run them in sequence automatically. Way cleaner and simpler than dealing with promise chains!

Your functions aren’t returning promises and the multi-element processing isn’t sequenced right. Hit this same issue when I built a report generator that turned DOM elements into images. You need each function to return a promise. For functions handling multiple elements like createDetails and buildSummary, use Promise.all to wait for all html2canvas operations before moving forward. Here’s how I solved it: function createDetails() { const promises = ; $(‘.details_table_row’).each(function(i, elem) { promises.push( html2canvas(elem).then(function(canvas) { elem.appendChild(canvas); const canvasData = canvas.toDataURL(); const obj = { src: canvasData, height: 400 }; results.push(obj); }) ); }); return Promise.all(promises); } Then chain them: generateHeader() .then(() => createDetails()) .then(() => buildSummary()) .then(() => console.log(‘All done’)); This way each function finishes all its async work before the next one kicks off.

Your functions aren’t returning promises, so $.when() has nothing to wait for. And honestly, managing all these promise chains manually gets messy quick.

I’ve built similar canvas processing workflows - they get complicated fast when you need proper sequencing and error handling. You end up with nested promise chains that are a nightmare to debug.

Better solution: use an automation platform like Latenode to handle the orchestration. Set up a workflow that manages the sequencing automatically, with built-in error handling and retry logic.

With Latenode, you create nodes for each operation (header generation, details processing, summary building) and connect them in order. It handles all the promise stuff behind the scenes. Plus you get monitoring and can modify the workflow without touching code.

Switched to this for our canvas processing pipeline and it killed all the async headaches. The workflow is visual, way easier to maintain, and handles edge cases better than manual promise chaining.

Had the same canvas sequencing headache recently. Your functions aren’t returning anything, so $.when() just fires all three at once instead of waiting. Hit this exact issue when processing multiple PDF sections. What fixed it for me was wrapping everything in one promise that handles the sequence internally. Don’t try making each function return promises separately - create one master function that awaits each step. Also, jQuery’s each() makes promise handling messy. Switched to regular for loops and the async flow became way more predictable. The trick is letting html2canvas finish completely before starting the next batch, otherwise you get canvas conflicts and wonky results.