Andrew J
Andrew J

Reputation: 3

How to get 3 functions to run synchronously in NodeJS

First question ever. Learned from StackOverflow for years. Just cant figure this out.

I've tried to wrap my head around callbacks, promises and async/await - I'm just not seeing it. Can someone please help?

I just cant get it to do: 1, then 2, then 3.

  1. Download a PDF
  2. Convert PDF to JPGs
  3. Delete PDF
const http = require('http');
const fs = require('fs');
const { exec } = require("child_process");
const targetUrl = 'http://domain/fileProxy.ashx?token=';
const previewpath = 'previews/';

var token = '66a7e572-e2fb-4fb4-87a9-6e19d675357f';
var orderNo = '121212';

function getPdf() {
    var file = fs.createWriteStream(orderNo+ ".pdf");
    http.get(targetUrl+token, function(response) {
        response.pipe(file);
        console.log('downloaded');
    });
}
    
function makeJpgs() {
    exec("magick -density 150 -quality 100% " + orderNo + ".pdf " + previewpath + orderNo + ".jpg");
    console.log('converted');
}

function deletePdf() {
    fs.unlink(orderNo+ ".pdf", (err) => {
        if (err) {
            throw err;
        }
    });
    console.log('deleted');
}

getPdf();
makeJpgs();
deletePdf();

Upvotes: 0

Views: 117

Answers (1)

slebetman
slebetman

Reputation: 113926

The traditional way of doing it is to continue execution in the callback. The minimal modification needed to get your code working:

function getPdf() {
    var file = fs.createWriteStream(orderNo+ ".pdf");
    http.get(targetUrl+token, function(response) {
        response.pipe(file);
        console.log('downloaded');
        makeJpgs(); // CONTINUED HERE!
    });
}
    
function makeJpgs() {
    // 
    exec("magick -density 150 -quality 100% " + orderNo + ".pdf " + previewpath + orderNo + ".jpg", function (err) {
        if (err) {
            console.error(err);
        }
        else {
            deletePdf(); // CONTINUED HERE!
        }
    });
    console.log('converted');
}

function deletePdf() {
    fs.unlink(orderNo+ ".pdf", (err) => {
        if (err) {
            console.error(err); // You can't really throw asynchronously
        }
        else {
            // Deletion process completes here.
            console.log('deleted');
        }
    });
    // console.log('deleted'); // Note: The file haven't even started being deleted here
}

getPdf();

With Promises you can make your code a bit more readable:

const util = require('util');
const http = require('http');
const fs = require('fs');
const child_process = require("child_process");
const targetUrl = 'http://domain/fileProxy.ashx?token=';
const previewpath = 'previews/';

var token = '66a7e572-e2fb-4fb4-87a9-6e19d675357f';
var orderNo = '121212';

const exec = util.promisify(child_process.exec);
const unlink = util.promisify(fs.unlink);
const get = function (url) {
    return new Promise(function(ok,fail){
        http.get(targetUrl+token, function(response) {
            response.pipe(file);
            ok();
        })
        .on('error',fail);
    });
}

function getPdf() {
    var file = fs.createWriteStream(orderNo+ ".pdf");
    return get(targetUrl+token);
}
    
function makeJpgs() {
    return exec("magick -density 150 -quality 100% " + orderNo + ".pdf " + previewpath + orderNo + ".jpg");
}

function deletePdf() {
    return unlink(orderNo+ ".pdf", (err) => {
        if (err) {
            throw err;
        }
    });
}

getPdf().then(function(){
    console.log('downloaded');
    return makeJpgs();
}).then(function(){
    console.log('converted');
    deletePdf();
}).then(fuction(){
    console.log('deleted');
});

Now that your functions return promises you can use async/await:

async function main () {
    await getPdf();
    console.log('downloaded');
    await makeJpgs();
    console.log('converted');
    await deletePdf();
    console.log('deleted');
}

main().then('done');

Upvotes: 1

Related Questions