使用Javascript在Google Drive中创建树目录结构

使用Javascript在Google Drive中创建树目录结构,javascript,google-api,google-drive-api,google-api-js-client,Javascript,Google Api,Google Drive Api,Google Api Js Client,我正在尝试用GoogleDriveJavaScriptAPI构建一个简单的目录树。我想我应该检查文件夹是否存在并创建它,然后最终添加它的子文件夹。因此,我构建了以下函数: function createFolder(name, parent) { if (!parent) parent = 'root'; var fileMetadata = { 'name': name, 'mimeType': 'application/vnd.google-a

我正在尝试用GoogleDriveJavaScriptAPI构建一个简单的目录树。我想我应该检查文件夹是否存在并创建它,然后最终添加它的子文件夹。因此,我构建了以下函数:

function createFolder(name, parent) {
    if (!parent) parent = 'root';
    var fileMetadata = {
        'name': name,
        'mimeType': 'application/vnd.google-apps.folder',
        'parent': parent
    };
    gapi.client.drive.files.create({
        'resource': fileMetadata,
        'fields': 'id'
    }).then(function (res) {console.log(res); return res.result['id'];}, function (err) {console.log(err); return null;});
}

function getFolder(name, parent) {
    if (!parent) parent = 'root';
    gapi.client.drive.files.list({
        'pageSize': 1,
        'fields': "nextPageToken, files(id, name, mimeType, parents)",
        'q': "mimeType='application/vnd.google-apps.folder' \
                    and '" + parent + "' in parents \
                    and name = '" + name + "'"
    }).then(
        function (res) {console.log(res); var ret = res.result.files.length > 0 ? res.result.files[0]['id'] : null; return ret;},
        function (err) {console.log(err);return null;}
    );
}

function checkPhrFolder() {
    var phr = getFolder('Personal Health Record');
    console.log('get folder: '+phr);
    if (!phr) {
        console.log('creating ...');
        phr = createFolder('Personal Health Record');
    }
}
这只是检查我的第一个目录是否存在,如果不存在,则创建它。问题是调用是异步的(使用“then Promissions”),因此函数不会返回任何内容(例如getFolder永远不会返回文件夹的id),因此我想知道,鉴于异步调用的性质,递归创建多个文件夹的正确方法是什么。我是否需要放置一个总是被调用的控制器函数并选择下一步要做什么


谢谢大家!

在本例中,我发现新的异步javascript语法更容易理解

方法 您正在同步运行函数
checkPhrFolder
,而依赖于异步api调用的其他两个函数正在等待解析承诺以返回值。在同步
checkphr文件夹
execution中计算phr时,这将导致phr未定义

基本上,为了实现这一点,您应该链接您的承诺解决方案,以便正确使用它们的返回值。尽管新的javascript语法使您能够用更少的代码行编写异步函数。 使用关键字
async
await
可以控制解析流,基本上在进行正确的赋值之前等待异步函数返回

例子 这样,您的
checPhrFolder
功能将几乎像以前一样易于阅读。在同步上下文中使用
checkPhrFolder
函数时,可以将其返回值包装在相同的
then/catch
语句中

参考文献

在本例中,我发现新的异步javascript语法更容易理解

方法 您正在同步运行函数
checkPhrFolder
,而依赖于异步api调用的其他两个函数正在等待解析承诺以返回值。在同步
checkphr文件夹
execution中计算phr时,这将导致phr未定义

基本上,为了实现这一点,您应该链接您的承诺解决方案,以便正确使用它们的返回值。尽管新的javascript语法使您能够用更少的代码行编写异步函数。 使用关键字
async
await
可以控制解析流,基本上在进行正确的赋值之前等待异步函数返回

例子 这样,您的
checPhrFolder
功能将几乎像以前一样易于阅读。在同步上下文中使用
checkPhrFolder
函数时,可以将其返回值包装在相同的
then/catch
语句中

参考文献

我使用传统方法构建我的dirs populator,方法如下:

    var phrFolderManager = {
        currentName: null,
        currentParent: null,
        folders: {
            '/PersonalHealthRecord': null,
            '/PersonalHealthRecord/Some': null,
            '/PersonalHealthRecord/Dirs': null,
            '/PersonalHealthRecord/ForMe': null
        },
        addFolder: function (name, id) {
            this.folders[name] = id;
        },
        getFolderId: function (name) {
            return this.folders[name];
        },
        refresh: function (forced) {
            console.log('next step ' + forced + ' ...');
            console.log(this.folders);
            // find the next null in our folder list
            for (k in this.folders) {
                this.currentName = k;
                if (!this.folders[k]) {
                    var parts = k.split('/');
                    if (parts.length == 2) {
                        // this is our base dir inside root
                        if (forced) {
                            this.createFolder(parts[1], 'root');
                        } else {
                            this.getFolder(parts[1], 'root');
                        }
                    } else {
                        var parent = parts.slice(0, -1).join('/');
                        var name = parts[parts.length - 1];
                        var parent_id = this.folders[parent];
                        if (forced) {
                            this.createFolder(name, parent_id);
                        } else {
                            this.getFolder(name, parent_id);
                        }
                    }
                    break;
                } else {
                    console.log('... defined as ' + this.folders[k]);
                }
            }
        },
        getFolder: function (name, parent) {
            //M.toast({html: 'check da pasta '+name,classes: 'rounded'});
            if (!parent) parent = 'root';
            this.currentParent = parent;
            console.log('getFolder ' + name + ' ' + parent);
            var res = gapi.client.drive.files.list({
                'pageSize': 1,
                'fields': "files(id, name, mimeType, parents)",
                'q': "mimeType='application/vnd.google-apps.folder' \
                        and '" + parent + "' in parents \
                        and name = '" + name + "'"
            }).then(
                function (res) {
                    console.log(res);
                    if (res.result.files.length > 0) {
                        this.folders[this.currentName] = res.result.files[0]['id'];
                        this.refresh(false);
                    } else {
                        this.refresh(true);
                    }
                },
                function (err) {
                    console.log('error in getFolder: ' + err)
                },
                this
            );
        },
        createFolder: function (name, parent) {
            M.toast({
                html: 'criando pasta ' + name,
                classes: 'rounded'
            });
            if (!parent) parent = 'root';
            console.log('createFolder ' + name + ' ' + parent);
            var fileMetadata = {
                'name': name,
                'mimeType': 'application/vnd.google-apps.folder',
                'parents': [parent]
            };
            gapi.client.drive.files.create({
                'resource': fileMetadata,
                'fields': 'id'
            }).then(
                function (res) {
                    console.log(res);
                    this.folders[this.currentName] = res.result['id'];
                    this.refresh();
                },
                function (err) {
                    alert('Problem creating ' + this.currentName + ' PersonalHealthRecord structure');
                },
                this
            );
        }
    };

我使用传统的方法构建我的dirs populator,如下所示:

    var phrFolderManager = {
        currentName: null,
        currentParent: null,
        folders: {
            '/PersonalHealthRecord': null,
            '/PersonalHealthRecord/Some': null,
            '/PersonalHealthRecord/Dirs': null,
            '/PersonalHealthRecord/ForMe': null
        },
        addFolder: function (name, id) {
            this.folders[name] = id;
        },
        getFolderId: function (name) {
            return this.folders[name];
        },
        refresh: function (forced) {
            console.log('next step ' + forced + ' ...');
            console.log(this.folders);
            // find the next null in our folder list
            for (k in this.folders) {
                this.currentName = k;
                if (!this.folders[k]) {
                    var parts = k.split('/');
                    if (parts.length == 2) {
                        // this is our base dir inside root
                        if (forced) {
                            this.createFolder(parts[1], 'root');
                        } else {
                            this.getFolder(parts[1], 'root');
                        }
                    } else {
                        var parent = parts.slice(0, -1).join('/');
                        var name = parts[parts.length - 1];
                        var parent_id = this.folders[parent];
                        if (forced) {
                            this.createFolder(name, parent_id);
                        } else {
                            this.getFolder(name, parent_id);
                        }
                    }
                    break;
                } else {
                    console.log('... defined as ' + this.folders[k]);
                }
            }
        },
        getFolder: function (name, parent) {
            //M.toast({html: 'check da pasta '+name,classes: 'rounded'});
            if (!parent) parent = 'root';
            this.currentParent = parent;
            console.log('getFolder ' + name + ' ' + parent);
            var res = gapi.client.drive.files.list({
                'pageSize': 1,
                'fields': "files(id, name, mimeType, parents)",
                'q': "mimeType='application/vnd.google-apps.folder' \
                        and '" + parent + "' in parents \
                        and name = '" + name + "'"
            }).then(
                function (res) {
                    console.log(res);
                    if (res.result.files.length > 0) {
                        this.folders[this.currentName] = res.result.files[0]['id'];
                        this.refresh(false);
                    } else {
                        this.refresh(true);
                    }
                },
                function (err) {
                    console.log('error in getFolder: ' + err)
                },
                this
            );
        },
        createFolder: function (name, parent) {
            M.toast({
                html: 'criando pasta ' + name,
                classes: 'rounded'
            });
            if (!parent) parent = 'root';
            console.log('createFolder ' + name + ' ' + parent);
            var fileMetadata = {
                'name': name,
                'mimeType': 'application/vnd.google-apps.folder',
                'parents': [parent]
            };
            gapi.client.drive.files.create({
                'resource': fileMetadata,
                'fields': 'id'
            }).then(
                function (res) {
                    console.log(res);
                    this.folders[this.currentName] = res.result['id'];
                    this.refresh();
                },
                function (err) {
                    alert('Problem creating ' + this.currentName + ' PersonalHealthRecord structure');
                },
                this
            );
        }
    };

很好的提示亚历山德罗,它工作得很好,而且在2020年似乎得到了很大的支持。非常优雅。谢谢@PatricioStegmann,请接受答案,以便社区更容易找到。对不起,Alessandro!我是新来的,甚至没有注意到接受按钮在哪里。英雄联盟修正了。很好的提示亚历山德罗,效果很好,这似乎在2020年得到了很大的支持。非常优雅。谢谢@PatricioStegmann,请接受答案,以便社区更容易找到。对不起,Alessandro!我是新来的,甚至没有注意到接受按钮在哪里。英雄联盟固定的。