0
function GetFolders(callback) {

var query = new CamlBuilder().Where().TextField("ContentType").EqualTo("Folder").ToString();
var hostweburl = decodeURIComponent(getQueryStringParameter("SPHostUrl"));
var scriptbase = hostweburl + '/_layouts/15/';

$.getScript(scriptbase + 'SP.RequestExecutor.js', function () {
    sendRequest(query, function myfunction() {
        var listEnumerator = spItems.getEnumerator();
        var items = [];
        var item;
        while (listEnumerator.moveNext()) {
            item = listEnumerator.get_current();
            items.push({ "title": item.get_item("FileLeafRef"), "lazy": true });;
        }
        callback(items);
    })
});
}    
function InitTree() {
$("#tree").fancytree({
    lazyLoad: function lazyLoad(event, data) {
        var result = [];
        $.when(GetFolders(function (items) {
            //Items array has 5 items now
            result = items;
        })).then(data.result = result);

        data.result = result;
        }
});
}
$(document).ready(function () {
    InitTree();
});

GetFolders() is a function that loads items from the server. it is sharepoint JSOM code.

When I expand the tree node "LazyLoad" function is called but it does not wait for the GetFolders() function to get items from the server and assign to result array but it goes to the next line of the $.when().then() and assign data.result to result which is an empty array.

I want to wait for the execution of GetFolders() function and then assign data.result to result array that has 5 items.

Update Following code worked.

function GetFolders(dfd) {
var deferredObject = $.Deferred();
var query = new CamlBuilder().Where().TextField("ContentType").EqualTo("Folder").ToString();
var hostweburl = decodeURIComponent(getQueryStringParameter("SPHostUrl"));
var scriptbase = hostweburl + '/_layouts/15/';

$.getScript(scriptbase + 'SP.RequestExecutor.js', function () {
    sendRequest(query, function myfunction() {
        var listEnumerator = spItems.getEnumerator();
        var item;
        var items = [];
        while (listEnumerator.moveNext()) {
            item = listEnumerator.get_current();
            items.push({ "title": item.get_item("FileLeafRef"), "lazy": true });;
        }
        dfd.resolve(items);
    })
});
}

function InitTree() {
$("#tree").fancytree({
    lazyLoad: function lazyLoad(event, data) {
        data.result = $.Deferred(function (dfd) {
            GetFolders(dfd);
        });
    }
});
}
$(document).ready(function () {
    InitTree();
});
Ali
  • 1,015
  • 14
  • 40

1 Answers1

0

The argument to .then() must be a function. It will be called when the promise is resolved.

I am loading items in a tree control using lazy load functionality.

function InitTree() {
    $("#tree").fancytree({
        lazyLoad: function lazyLoad(event, data) {
            var result = [];
            $.when(GetFolders(function (items) {
                //Items array has 5 items now
                result = items;
            })).then(function() {
                data.result = result);
            });
        }
    });
}
chrki
  • 6,143
  • 6
  • 35
  • 55
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • I put a break point in "then" and inside "when" function and data.result line which is next to "then", "then" triggers first and assigns blank array and data.result which is next to the "then" function calls second and "when" triggers at last. Do I need to add anything in GetFolders() function? – Ali May 19 '16 at 03:15
  • `GetFolders` has to return a promise that completes when all its asynchronous calls have completed. – Barmar May 19 '16 at 03:18
  • Original question updated, where can I call promise? – Ali May 19 '16 at 03:26
  • `$.getScript` returns a promise. So just use `return $.getScript(...)`. – Barmar May 19 '16 at 03:36
  • If I use return with $.getscript(...) I get 404 error in console my url /function%20(items)%20%7B%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20result%20=%20[%7B%20%22title%22:%20%22Sub%20item%22,%20%22lazy%22:%20true%20%7D,%20%7B%20%22title%22:%20%22Sub%20folder%22,%20%22folder%22:%20true,%20%22lazy%22:%20true%20%7D];%20//items;%20%20%20%20%20%20%20%20%20%20%20%20%7D?_=1463630479823 – Ali May 19 '16 at 04:33
  • GetFolder function also taking a callback function as parameter and call that function when items are returned, can I do something with that? – Ali May 19 '16 at 04:56
  • I don't see how returning the value from `$.getScript` can change the URL like that. – Barmar May 19 '16 at 15:46
  • Since `GetFolder` takes a callback parameter, you don't need to use `$.when` and `.then` -- just put everything into the callback. Callback functions and promises are ways to accomplish essentially the same thing (promises are more general and flexible). – Barmar May 19 '16 at 15:48
  • The line result = items; is already in callaback and works fine but the problem is when GetFolder function is called control does not stop here and keep executing the lazyload function and moves to the next line which is data.result = result; at this stage result is an empty array and and lazyload finishes execution without waiting for for the result of GetFolder function. again coming to original question how can I stop execution of Lazy load function to wait for the GetFolder output and then go to next line and execute rest of the lazy load function? – Ali May 20 '16 at 01:15
  • `GetFolder` is asynchronous. Anything that needs to wait for it to finish must be done in its callback function. See http://stackoverflow.com/questions/23667086/why-is-my-variable-undefined-after-i-modify-it-inside-of-a-function-asynchron?newsletter=1&nlcode=97716%7c4ba7 – Barmar May 20 '16 at 01:20