1

I'm trying to fire a function when all the templates are loaded. This is done via a loadTemplate function for each template.

My problem is how to listen for all the .then() to finish, and only after that to fire my foo() function.

I've tried using when() and promise, but I haven't been successful in binding that to the outside each, while I've manage to bind it to the loadTemplate (which isn't what I'm looking for).

I could always bind each loadTemplate to a counter, and on each iteration check if the counter has reached the number of templates on the each, but I'm sure there's a more elegant way to do this.

Here's the loop code:

    $.each(templates.hbs, function(idx, template) {
        loadTemplate(template.name)
          .then(function(templateStr){
            var compiledTemplate = Handlebars.compile(templateStr);
            if(template.isPartial){
              Handlebars.registerPartial(template.key, compiledTemplate);
            }
            templates[template.key] = compiledTemplate;
          });
      });

and the function to fire after:

    function templateDone(){
      console.log("done!");
    }

Thanks for the help!

Edit: Including the loadTemplate code as well:

    function loadTemplate (template) {
      return new Promise(function (resolve, reject) {
        $.ajax({
          url: config.wwwroot + '/folder/' + template + '.hbs',
          async: false,
          success: function (result) {
            resolve(result);
          },
          error: reject
        });
      });
    }
Ineze
  • 389
  • 4
  • 17

2 Answers2

2

As your loadTemplate function returns a promise, you can use .when(). See the documentation example for a case of waiting for multiple promises to be resolved.

You could do something like:

var promises = [];

$.each(templates.hbs, function (idx, template) {
    promises.push(loadTemplate(template.name));
});

$.when.apply($, promises).then(templateDone);

As for your loadTemplate function, you don't need to create your own promise. $.ajax returns a promise by default.

function loadTemplate(template) {
    return $.ajax({
        /* ... */
    });
}

See if that makes a difference? Also try without the async property. I'm not sure why that would fix it but it is worth trying.

Ben Guest
  • 1,488
  • 2
  • 17
  • 29
1

You can write simple condition to check if all the templates are loaded like this

var loaded_template = 0;  
$.each(templates.hbs, function(idx, template) {
    loadTemplate(template.name)
      .then(function(templateStr){
        var compiledTemplate = Handlebars.compile(templateStr);
        if(template.isPartial){
          Handlebars.registerPartial(template.key, compiledTemplate);
        }
        templates[template.key] = compiledTemplate;
        loaded_template++;
        if(loaded_template == templates.hbs.length){
         foo();
        }
      });
  });

I hope this works for you. You can use this approach even if you are loading templates with ajax calls. Calling function after $.each wont work if you are loading templates with ajax..

Harry Bomrah
  • 1,658
  • 1
  • 11
  • 14
  • Yes, this works. I was wondering, however, if there was a way to do this by events rather than with a counter – Ineze Oct 08 '15 at 10:34
  • Counter is good and efficient way as I said if you want to load templates even using ajax calls. There is no callback event for $.each function so there is no event raised when $.each is completed. – Harry Bomrah Oct 08 '15 at 10:37