一个函数在另一个函数完成之前加载

时间:2013-07-09 17:43:20

标签: javascript jquery onedrive

我正在使用javascript和skydrive API编写网站。

这是我的代码:

var clientId = '00000000400FFB5A';
var redirectUri = "http://milmantasimmigration.com/skydrive/test/test.html";

WL.init({
    client_id: clientId,
    redirect_uri: redirectUri
});

WL.Event.subscribe("auth.login", onLogin);
WL.Event.subscribe("auth.sessionChange", onSessionChange);

var session;
var companyFolders;
var reportFolders;
var reports;

session = WL.getSession();
if (session) {
    log("You are already signed in!");
    getCompanyFolders();
} else {
    WL.login({
        scope: "wl.signin"
    });
}

function onLogin() {
    var session = WL.getSession();
    if (session) {
        log("You are signed in!");
    }
}

function onLogout() {
    WL.logout();
    log("You are logged out!");
}

function onSessionChange() {
    var session = WL.getSession();
    if (session) {
        log("Your session has changed.");
    }
}

function getCompanyFolders() {
    var getCompanyFoldersDeferred = $.Deferred();

    WL.api({
        path: "/me/skydrive/shared",
        method: "GET"
    }).then(

    function(response) {
        companyFolders = [];
        reportFolders = [];
        reports = [];
        for (var i = 0; i < response.data.length; i++) {
            if (response.data[i].type == "folder") {
                companyFolders.push(response.data[i]);
                getReportFolders(response.data[i].id + "/files/", companyFolders.length - 1);
            }
        }
        $.when.apply($, companyFolders).done(function() {
            getCompanyFoldersDeferred.resolve();
        });
    }, function(response) {
        log("Cannot get files and folders: " + JSON.stringify(response.error).replace(/,/g, ",\n"));
    });

    return getCompanyFoldersDeferred.promise();
}

function getReportFolders(path, index1) {
    var getReportFoldersDeferred = $.Deferred();
    //var index2 = 0;

    WL.api({
        path: path,
        method: "GET"
    }).then(

    function(response) {
        reportFolders[index1] = [];

        reports[index1] = [];
        for (var i = 0; i < response.data.length; i++) {
            if (response.data[i].type == "folder") {
                reportFolders[index1].push(response.data[i]);
                //index2++;
                getReports(response.data[i].id + "/files/", index1, reportFolders[index1].length - 1);
            }
        }
        $.when.apply($, reportFolders).done(function() {
            getReportFoldersDeferred.resolve();
        });
    }, function(response) {
        log("Cannot get files and folders: " + JSON.stringify(response.error).replace(/,/g, ",\n"));
    });
    return getReportFoldersDeferred.promise();
}

function getReports(path, index1, index2) {
    var getReportsDeferred = $.Deferred();
    //var index3 = 0;

    WL.api({
        path: path,
        method: "GET"
    }).then(

    function(response) {
        reports[index1][index2] = [];

        for (var i = 0; i < response.data.length; i++) {
            if (response.data[i].type == "file") {
                reports[index1][index2].push(response.data[i]);
                //index3++;
            }
        }
        $.when.apply($, reports).done(function() {
            getReportsDeferred.resolve();
        });
    }, function(response) {
        log("Cannot get files and folders: " + JSON.stringify(response.error).replace(/,/g, ",\n"));
    });
    return getReportsDeferred.promise();
}

getCompanyFolders().done(function() {
    showReportsHTML();
});

function showReportsHTML() {
    for (var i = 0; i < companyFolders.length; i++) {
        for (var j = 0; j < reportFolders[i].length; j++) {
            for (var k = 0; k < reports[i][j].length; k++) {
                alert(reports[i][j][k].name);
            }
        }
    }
}

function log(x) {
    alert(x);
}   

这两行

getCompanyFolders();
showReportsHTML();

在getCompanyFolders()函数完成其作业后,一个接一个地执行函数。但showReportsHTML()是在getCompanyFolders()填充报表3D数组之前执行的。

如何在getCompanyFolders()完全完成后启动showReportsHTML()函数?

2 个答案:

答案 0 :(得分:1)

WL.api()是异步的,因此继续执行下一个函数。

每个函数都可以返回延迟对象:

getCompanyFolders().done(function() {
    showReportsHTML();
});

function getCompanyFolders() {
    var getCompanyDeferred = $.Deferred();

    WL.api({
        path: "/me/skydrive/shared",
        method: "GET"
    }).then(function(response) {
        var deferreds = []
        foreach(item in response) { 
            deferreds.push(getReportFolders());
        }

        $.when.apply($, deferreds).done(function() {
            getCompanyDeferred.resolve();
        });

    });

    return getCompanyDeferred.promise();
}

这显然是一个简化的例子。 getReportFoldersgetReports的结构看起来非常相似。如果您需要我进一步举例,请告诉我。

根据您的更新进行修改

还有几件事。首先,

getCompanyFolders();应该是:

getCompanyFolders().done(function() {
    showReportsHTML();
});

其次,$.when()接受deferredpromise个对象,在您的情况下,这些对象是函数的返回值。

因此,在getCompanyFolders中,调用getReportFolders会返回您的延迟对象。这些结果应该被推入数组并传递给$.when

function getCompanyFolders() {
    var getCompanyFoldersDeferred = $.Deferred();

    WL.api({
        path: "/me/skydrive/shared",
        method: "GET"
    }).then(

    function(response) {
        companyFolders = [];
        reportFolders = [];
        reports = [];
        var deferreds = []; // <------- new array to hold deferred objects
        for (var i = 0; i < response.data.length; i++) {
            if (response.data[i].type == "folder") {
                companyFolders.push(response.data[i]);
                deferreds.push(getReportFolders(response.data[i].id + "/files/", companyFolders.length - 1)); // <------- hang on to the results from this function
            }
        }
        $.when.apply($, deferreds).done(function() { // <--- wait on all the deferreds to resolve
            getCompanyFoldersDeferred.resolve();
        });
    }, function(response) {
        log("Cannot get files and folders: " + JSON.stringify(response.error).replace(/,/g, ",\n"));
    });

    return getCompanyFoldersDeferred.promise();
}

getReportsFolders需要进行类似的更改。

getReports无需等待其他任何事情来解决。一旦我们收到回调,我们就完成了:

function getReports(path, index1, index2) {
    var getReportsDeferred = $.Deferred();
    //var index3 = 0;

    WL.api({
        path: path,
        method: "GET"
    }).then(

    function(response) {
        reports[index1][index2] = [];

        for (var i = 0; i < response.data.length; i++) {
            if (response.data[i].type == "file") {
                reports[index1][index2].push(response.data[i]);
                //index3++;
            }
        }

        getReportsDeferred.resolve();  // <---- all done, nothing else to wait on.

    }, function(response) {
        log("Cannot get files and folders: " + JSON.stringify(response.error).replace(/,/g, ",\n"));
    });
    return getReportsDeferred.promise();
}

答案 1 :(得分:0)

这是因为getCompanyFolders正在调用异步函数。如果您希望在此功能完成后发生某些事情,则必须提供回调函数:

function getCompanyFolders(callback) {
    companyFolders = [];

    WL.api({
        path: "/me/skydrive/shared",
        method: "GET"
    }).then(

    function(response) {
        reportFolders = [];
        reports = [];
        for (var i = 0; i < response.data.length; i++) {
            if (response.data[i].type == "folder") {
                companyFolders[companyFolders.length] = response.data[i];
                getReportFolders(response.data[i].id + "/files/", companyFolders.length - 1);
            }
        }
        callback();
    }, function(response) {
        log("Cannot get files and folders: " + JSON.stringify(response.error).replace(/,/g, ",\n"));
        callback();
    });
}

现在您可以致电getCompanyFolders并简单地将showReportsHTML作为参数传递。

getCompanyFolders(showReportsHTML);