0

I have a method that performs an asynchronous ajax request to get some permission information from the server (SharePoint) to beeing cached via JS so that I can access it for CSR. Sometimes this takes a little longer (500ms)... not always, but sometimes the rest of the script is loaded so fast, that it needs the permission before the ajax request ist completed entirely.

Is there a simple method to just delay the output of the method? I tried different stuff with SetTimeout() but notthing worked out.

Here is the simplyfied code...

var Permissions = {
    get: function(key) {
        while (this.cacheLoaded != true) {
            wait(100); //<-- This is what I need
        }
        return (typeof this[key] != 'undefined' && this[key] == true) ? true : false;       
    },
    cacheLoaded: false,
    buildCache: function () {
        // load permissions asynchronously by ajax
        .
        .
        .
        Permissions.cacheLoaded = true;
    }
}
Permissions.buildCache();
.
.
.
doLotsOfOtherStuff();
.
.
.    
//Here is the actual call of the get-function:
if (Permission.get('ALOW_DELETE')) {
    deleteSomething();
}

Of course I could switch the Ajax requst to be synchronous. But this would delay the whole script loading. So actually I want to delay jsut the getter for a couple of milliseconds until the request is finished.

Dave
  • 263
  • 3
  • 12
  • 4
    You don't have to make the request synchronous, but you really can't reliably do anything else until the initial request completes anyway. All of the `doLotsOfOtherStuff` etc. has to be done after the cache is loaded -- in the ajax callback. – Explosion Pills Oct 29 '15 at 22:51
  • You can't `wait` [just yet](https://jakearchibald.com/2014/es7-async-functions/) - you need to put the logic that needs data inside a callback (or Promise handler) for the AJAX request. – joews Oct 29 '15 at 22:53
  • Have you seen [this](http://stackoverflow.com/questions/3709597/wait-until-all-jquery-ajax-requests-are-done)? – Shawn Mehan Oct 29 '15 at 22:54

2 Answers2

0

There is _spYield(a,b) in init.js which is declared as:

function _spYield(b, a) {
if (a > 0)
    window.setTimeout(function() {
        _spYield(b, a - 1)
    }
    , 0);
else
    b()

}

Danny '365CSI' Engelman
  • 16,526
  • 2
  • 32
  • 49
-1

I'll skip the part about this being extremely bad practice and to always use timeouts and callbacks.

Because js is single threaded, you don't have many options. I would go with an empty loop, but as @joews says, that will stall the execution, and cacheLoaded will never be set to true;

while (this.cacheLoaded != true) { /*Stall*/ }

EDIT:

Callback Solution:

get: function(key, callback) {
        var fn = function { 
            if(this.cacheLoaded != true) 
                window.setTimeout(fn, 500);
            else
                callback((typeof this[key] != 'undefined' && this[key] == true) ? true : false);
        };
        fn();      
    }

Then call it like so:

Permission.get('ALOW_DELETE', function(result) {if(result) deleteSomething();});
Chloe
  • 483
  • 4
  • 14
  • 1
    That won't work because JS execution will stay on the current call stack. `cacheLoaded` can only be set to true on a later tick of the event loop, which the JS engine will never get to. – joews Oct 29 '15 at 22:54
  • @joews You're correct. I've noted that and added an actual solution. – Chloe Oct 29 '15 at 23:06