Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JS Globalize - load json cldr

I have a problem with the latest version of globalize.js. To work with it I had to load the cldr modules and language definitions.

Now I had this example from the globalize docs:

// loading needed modules
$.get('/Scripts/cldr/supplemental/likelySubtags.json', Globalize.load);
$.get('/Scripts/cldr/main/en/numbers.json', Globalize.load);
$.get('/Scripts/cldr/main/de/numbers.json', Globalize.load);

// set current language
lobalize.locale('de-de');

My problem now is that the local json files are loaded async. That means at the moment where my script is try to set the current language, the modules are not yet loaded.

Now I tried to be smart and made this:

$.get('/Scripts/cldr/supplemental/likelySubtags.json', function (data) {
        Globalize.load(data);
        Globalize.locale('de-de');
});

$.get('/Scripts/cldr/main/en/numbers.json', Globalize.load);
$.get('/Scripts/cldr/main/de/numbers.json', Globalize.load);

This will work until I really used globalize format methode. Inside my HTML I use globalize inside a knockout binding like this:

<span data-bind="text: Globalize.formatNumber(SomeNumber, { maximumFractionDigits: 0 })"></span>

Now the "formatNumber" method is throwing an error because not all module are loaded at the moment the binding is happend.

My question is now, how can I sync up my JavaScript?

like image 865
Steffen Mangold Avatar asked Aug 13 '14 08:08

Steffen Mangold


1 Answers

There are actually 2 ways to solve the issue:

  1. Use $.ajax with async: false option to load your json modules.
  2. Use deferreds to have a single callback on all your ajax requests.

1. Using async: false

You can use more general method $.ajax instead of $.get (see description). It has async option:

By default, all requests are sent asynchronously (i.e. this is set to true by default). If you need synchronous requests, set this option to false.

So you can rewrite your requests as follows:

$.ajax({
    url: '/Scripts/cldr/supplemental/likelySubtags.json',
    type: 'GET',
    async: false,
    success: function(data) {
        Globalize.load(data);
    }
});

You do this for all 3 of your requests and then call:

// set current language
lobalize.locale('de-de');

Just like you did before. But now, since all requests are done synchronously, this code should work as expected. The downside of this solution is that it has synchronous requests which will cause some delays. That is why I suggest you the second option:

2. Using deferreds: You can use $.when() function to combine success callbacks of all three requests to one like this:

$.when($.get('/Scripts/cldr/supplemental/likelySubtags.json'), 
       $.get('/Scripts/cldr/main/en/numbers.json'), 
       $.get('/Scripts/cldr/main/de/numbers.json'))
.done(function(result1, result2, result3) {
    Globalize.load(result1[0]); //contains data of first executed request
    Globalize.load(result2[0]); //contains data of second executed request
    Globalize.load(result3[0]); //contains data of third executed request
    // set current language
    lobalize.locale('de-de');
    // here you should fire your knockout binding
});

The good thing is that all requests are now done asynchronously. But this would still not solve your knockout binding issue. To resolve it, ko.applyBindings should also be called in success callback, when all data is loaded.

like image 173
Ilya Luzyanin Avatar answered Sep 17 '22 22:09

Ilya Luzyanin