簡體   English   中英

具有Promise的Javascript遞歸函數

[英]Javascript recursive function with promises

以下功能用於通過對嵌入式Web服務器的HTTP調用刪除文件。 網絡服務器接受DELETE動詞來刪除文件; 它也可以在文件夾上使用,但前提是為空。

我想創建一個遞歸地請求文件夾內容的函數,將其全部刪除,然后刪除該文件夾。 使用諾言,我設法使它幾乎完全起作用。 頂部路徑“ /”中的文件被刪除,第一個文件夾“ / folder1 /”中的文件也被刪除,但是該函數退出,使“ / folder1 /”為空,而“ / folder2 /”保持不變。 在Firefox 40和Chrome 45中都嘗試過。有人可以發現任何錯誤嗎? 我已經嘗試了好幾天...

我認為這可能與jQuery Promise和標准Promise的混合使用有關,無法正確解析。

文件夾內容是通過API調用詢問的,該API返回一個類似這樣的對象數組:

[{"type": "dir", "name": ".", "size": "-"},
{"type": "dir", "name": "..", "size": "-"},
{"type": "dir", "name": "folder1", "size": "-"},
{"type": "dir", "name": "folder2", "size": "-"}
{"type": "file", "name": "file1", "size": "1211"},
{"type": "file", "name": "file2", "size": "1251"},]

這是主要功能。

function purgeSdcard() {
    printMessage("WARNING: Purging SDcard");

    function purgeCycle(fileList, path, file) {
        return new Promise(function(resolve, reject) {
            if (typeof(fileList) === 'undefined' || fileList.length === 0) resolve();
            if (typeof(file) === 'undefined') file = 0;
            if (file >= fileList.length) resolve();

            if (fileList[file].type === "dir") { // Directory
                if (fileList[file].name === "." || fileList[file].name === ".." || fileList[file].name === "system volume information") {
                    return purgeCycle(fileList, path, file + 1);
                }
                else {
                    return purge(path + fileList[file].name + "/")
                        .then(function(res) {
                            return deleteFile(path + fileList[file].name);
                        })
                        .then(function(res) {
                            console.log("purgeCycle(fileList, path, file + 1) " + fileList + path + file + 1);
                            return purgeCycle(fileList, path, file + 1);
                        });
                }
            }
            else { // File
                return deleteFile(path + fileList[file].name).then(
                    function(res) {
                        return purgeCycle(fileList, path, file + 1);
                    });
            }
        });
    }

    function purge(path) {
        if (typeof(path) === 'undefined') path = "/";
        return getFileList(path).then(
            function(fileList) {
                return purgeCycle(fileList, path);
            });
    }

    purge();
}

function getFileList(path, onDone) {
    if (typeof(path) === 'undefined') path = "/";
    return Promise.resolve($.ajaxQueue({
            url: path + "?dir",
            type: "GET",
            dataType: "json"
        }).done(function() {
            console.log("getFileList: " + path);
            if (typeof(onDone) === 'function') {
                onDone();
            }
        })
        .fail(function() {}));
}

function deleteFile(fileURL) {
    printMessage("ST &nbsp- File delete: " + fileURL);
    return Promise.resolve($.ajaxQueue({
            url: fileURL,
            type: "DELETE"
        }).done(function() {
            printMessage("OK &nbsp- File delete: " + fileURL);
        })
        .fail(function() {
            printError("ERR - File delete: " + fileURL);
        }));
}

我認為您的猜測是正確的,這可能是jQuery Promises / Deferred對象與JS內置Promises之間的沖突。

Promise.resolve()返回一個承諾,該承諾解析為傳遞給該函數的值,或者如果傳遞了一個承諾,則解析為該承諾解析為的值。 由於將其傳遞給jQuery.Deferred,它將解決此問題,因此, getFileList(...).then(fileList)調用getFileList(...).then(fileList) ,收到的fileList實際上就是Deferred對象。

在這種情況下,您可以在代碼中使用jQuery.Deferred對象,也可以在Promise中包裝$.ajaxQueue以便兼容。 您正在使用new PromisePromise.resolve使我相信您對jQuery.Deferred投入並不那么jQuery.Deferred ,所以這是使用包裝$.ajaxQueue版本的相關代碼$.ajaxQueue

function ajaxQueue(options) {
    return new Promise(function (resolve, reject) {
        $.ajaxQueue(options).done(function (val) {
            resolve(val);
        }).fail(function (err) {
            reject(err);
        });
    });
}

// returns Promise that resolves to a jQuery deferred value.
function getFileList(path, onDone) {
    if (typeof path === 'undefined') path = "/";
    return ajaxQueue({
        url: path + "?dir",
        type: "GET",
        dataType: "json"
    }).then(function (result) {
        console.log("getFileList: " + path);
        if (typeof onDone === 'function') {
            onDone();
        }
        // Pass along.
        return result;
    }).catch(function (err) { });
}

function deleteFile(fileURL) {
    printMessage("ST &nbsp- File delete: " + fileURL);
    return ajaxQueue({
        url: fileURL,
        type: "DELETE"
    }).then(function (result) {
        printMessage("OK &nbsp- File delete: " + fileURL);
        // Pass along result.
        return result;
    }).catch(function (err) {
        printError("ERR - File delete: " + fileURL);
    });
}

常規JS PromisejQuery.Deferred (除了可用的函數)之間的主要區別在於, then的返回值就是傳遞給隨后的then調用的東西。 因此,如果只記錄getFileListdeleteFile中的getFileList ,則傳遞結果很重要。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM