Почему тогда я не могу использовать обещанное решение? - PullRequest
0 голосов
/ 25 июня 2019

У меня есть функция, задача которой - просмотреть несколько файлов (которые используют значения из массива в качестве строительных блоков для имен файлов) и загрузить их, используя reduce. На данный момент это скорее хак, но логика Promise должна работать. За исключением того, что это не.t

Вот мой код:

function import_demo_files(data) {
    /**
     * Make a local copy of the passed data.
     */
    let request_data = $.extend({}, data);

    const get_number_of_files_1 = Promise.resolve({
        'data' : {
            'number_of_files' : 2
        }
    });

    return new Promise((resolve, reject) => {
        let import_files = get_number_of_files_1.then(function(response) {
            new Array(response.data.number_of_files).fill(request_data.step_name).reduce((previous_promise, next_step_identifier) => {
                let file_counter = 1;

                return previous_promise.then((response) => {
                    if( response !== undefined ) {
                        if('finished_import' in response.data && response.data.finished_import === true || response.success === false) {
                            return import_files;
                        }
                    }
                    const recursively_install_step_file = () => import_demo_file({
                        demo_handle: request_data.demo_handle,
                        'step_name': request_data.step_name,
                        'file_counter': file_counter

                    }).call().then(function(response) {
                        file_counter++;

                        if('file_counter' in response.data && 'needs_resume' in response.data) {
                            if(response.data.needs_resume === true) {
                                file_counter = response.data.file_counter;
                            }
                        }
                        return response.data.keep_importing_more_files === true ? recursively_install_step_file() : response
                    });
                    return recursively_install_step_file();
                }).catch(function(error) {
                    reject(error);
                });
            }, Promise.resolve())
        }).catch(function(error) {
            reject(error);
        });
        resolve(import_files);
    });
}

Теперь, когда я это сделаю:

const import_call = import_demo_files({ 'demo_handle' : 'demo-2', 'step_name' : 'post' });
console.log(import_call);

console.log возвращает мне, что import_call на самом деле является обещанием , и оно разрешено . Мне очень нравится, как return позволяет мне выйти из цепочки обещаний, но я понятия не имею, как правильно разрешить мою цепочку обещаний, поэтому ясно, что она помечена как решенная, когда это не так.

Я хотел бы сделать import_call.then(..., но на данный момент это не работает, он выполняет этот код здесь до того, как он действительно будет выполнен из-за неправильной обработки в import_demo_files.

1 Ответ

1 голос
/ 26 июня 2019

Асинхронная рекурсия внутри редукции - не самая простая вещь, на которой можно порезаться, и не сразу понятно, почему вы захотите, учитывая, что каждая итерация рекурсии идентична любой другой итерации.

Шаблон сокращения / рекурсии проще понять, когда в качестве внешних элементов выбраны следующие элементы:

1. the `recursively_install_step_file()` function
1. the `new Array(...).fill(...)`, as `starterArray`
1. the object passed repeatedly to `import_demo_file()`, as `importOptions`)

Этот подход устраняет необходимость в переменной file_counter, поскольку importOptions.file_counter может быть обновлено напрямую.

function import_demo_files(data) {
    // outer members
    let request_data = $.extend({}, data);
    const importOptions = {
        'demo_handle': request_data.demo_handle,
        'step_name': request_data.step_name,
        'file_counter': 1
    };
    const starterArray = new Array(2).fill(request_data.step_name);
    function recursively_install_step_file() {
        return import_demo_file(importOptions).then((res) => {
            if('file_counter' in res.data && 'needs_resume' in res.data && res.data.needs_resume) {
                importOptions.file_counter = res.data.file_counter; // should = be += ?
            } else {
                importOptions.file_counter++;
            }
            return res.data.keep_importing_more_files ? recursively_install_step_file() : res;
        });
    }

    // the reduce/recurse pattern
    return starterArray.reduce((previous_promise, next_step_identifier) => { // next_step_identifier is not used?
        let importOptions.file_counter = 1; // reset to 1 at each stage of the reduction?
        return previous_promise.then(response => {
            if(response && ('finished_import' in response.data && response.data.finished_import || !response.success)) {
                return response;
            } else {
                return recursively_install_step_file(); // execution will drop through to here on first iteration of the reduction
            }
        });
    }, Promise.resolve());
}

Может быть не на 100% правильным, но общая картина должна быть примерно правильной. Будьте готовы поработать над этим немного.

...