Создайте древовидную структуру каталогов в Google Диске с помощью Javascript - PullRequest
1 голос
/ 01 мая 2020

Я пытаюсь создать простое дерево каталогов с помощью Google Drive Javascript API. Я полагаю, что я должен проверить существование папки и создать ее, а затем добавить ее потомков. Поэтому я построил эти функции ниже:

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');
    }
}

Это просто проверяет, существует ли мой первый каталог, и если нет, создает его. Проблема заключается в том, что вызовы асин c (с использованием «затем обещаний»), поэтому функции ничего не возвращают (например, getFolder никогда не возвращает идентификатор папки), поэтому мне было интересно, как правильно рекурсивно создавать много папок с учетом характера асин c вызовов. Нужно ли ставить функцию контроллера, которая всегда вызывается, и выбирать, что делать дальше?

Спасибо!

Ответы [ 2 ]

0 голосов
/ 05 мая 2020

Я использовал традиционный способ построения моего 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
            );
        }
    };
0 голосов
/ 01 мая 2020

В этом случае я обнаружил, что новый асинхронный синтаксис javascript легче понять.

Approach

Вы выполняете функцию checkPhrFolder синхронно, в то время как две другие функции, зависящие от асинхронного вызова API, ожидают разрешения для разрешения, чтобы вернуть значение. Это приведет к тому, что phr будет неопределенным, когда вы оцените его в синхронном checkPhrFolder выполнении.

В основном, чтобы это работало, вы должны связать разрешение ваших обещаний, чтобы правильно использовать их возвращаемые значения. Новый синтаксис javascript позволяет писать асинхронные функции с меньшим количеством строк кода. С помощью ключевых слов async и await вы можете управлять потоком разрешения обещаний и, в основном, ждать, пока асинхронная функция вернется, прежде чем выполнить правильное назначение.

Пример

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

async function getFolder(name, parent) {
    if (!parent) parent = 'root';
    const res = await 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 + "'"
    });
    return res.result.files.length > 0 ? res.result.files[0]['id'] : null;
}

async function checkPhrFolder() {
  var phr = await getFolder('Personal Health Record');
  console.log('get folder: '+phr);
  if (!phr) {
      console.log('creating ...');
      phr = createFolder('Personal Health Record');
  }
}

В этом Таким образом, ваша функция checPhrFolder будет читаться почти так же легко, как и раньше. Когда вы будете использовать функцию checkPhrFolder в синхронном контексте, вы сможете заключить ее возвращаемое значение в тот же оператор then/catch.

Reference

Async / Await

...