4

In my Cordova project, I have a hook which does RequireJS optimization (r.js) on after_prepare. That optimization is inherently asynchronous, so my hook code returns before all optimization is fully finished.

For example, this causes issues when running cordova run browser: On the first page load, optimization has not finished yet and the site looks broken.

Is there a way to make the Cordovoa build process to block until a certain hook fires a callback? Or can the optimizer be run in a blocking/sync way?

An alternative I could think of is using a different process for optimization and busy-wait in the main for it to finish, but that looks like an overkill and bad practice to me.

Cedric Reichenbach
  • 8,970
  • 6
  • 54
  • 89

2 Answers2

7

You can use the built-in promise module to block Cordova from proceeding until the hook has resolved. Something along these lines:

#!/usr/bin/env node

var deferral;

function doSomethingAsync(){
    somethingAync
        .success(function(){
            deferral.resolve();
        })
        .fail(function(err){
            deferral.reject(err);
        });
}

module.exports = function(ctx) {
    deferral = ctx.requireCordovaModule('q').defer();
    doSomethingAsync();
    return deferral.promise;
};
DaveAlden
  • 30,083
  • 11
  • 93
  • 155
1

You don't need to call context, you can simply return a Promise from within the module.exports function

module.exports = context => {
    return new Promise(resolve => {
        setTimeout(() => resolve(), 1000);
    });
};

I tested and it works. The problem arises because in Cordova versions => 9 you cannot use context.requireCordovaModule('q')

If you don't want to use Promise, just do

module.exports = context => {
    var deferral = require('q').defer();
    doSomethingAsync(() => {
      deferral.resolve();
    });
    return deferral.promise;
};
João Pimentel Ferreira
  • 14,289
  • 10
  • 80
  • 109