Использование dojo / Deferred с асинхронными функциями и запросами - PullRequest
0 голосов
/ 02 апреля 2020

У меня проблема с получением некоторых запросов и функций для запуска в правильном порядке. Предположим, у меня есть 2 функции, которые создают 2 раскрывающихся списка (dropdown_a, dropdown_b). Последовательно create_a(items) должен сначала быть вызван до create_b(items). Фактически, create_a(items) создает dropdown_a, а затем содержит событие on('change'), которое вызывает function_b(items), что, в свою очередь, создает dropdown_b. Чтобы получить параметр items для каждой из этих функций, я сначала должен запросить службу REST. Без вставки тонны кода (он огромен) рабочий процесс будет выглядеть так:

function create_a(items):
    var projectNode = dom.byId("projectDropdown");
    ...
    var projectSelector = new Select({
        name: "projectSelect",
        id: "projectSelect",
        options: projectsOptions
    }).placeAt(projectNode).startup();
    dijit.byId('projectSelect').on('change', function (e) {
        var subprojectQuery = new esriQuery();
        ... // creates a query to get subproject items
        subprojectAccessQueryTask.execute(subprojectQuery,
            function (results) {
                let records = results.features;
                createSubprojectDropdown(records); // calls the subproject function
            },
            function (error) {
                console.log("query error: ", error);
            }
        }); // End of deferred Query Task for Project Name
    });
}

function create_b(items) {
    var subprojectNode = dom.byId("subprojectDropdown");
    var p = registry.byId('subprojectSelect');
    if (p) {
        p.destroyRecursive();
    }
    var subprojectSelector = new Select({
        name: "subprojectSelect",
        id: "subprojectSelect",
        options: subprojectsOptions
    }).placeAt(subprojectNode).startup();

    dijit.byId('subprojectSelect').on('change', function (e) {
        thisWidget.loadData(e, proj_type_obj);
    });
    thisWidget.loadData();
}

// Query 1 - Projects
var queryTask_a = new QueryTask();
queryTask_a.execute(query_a_obj,
    function (results) {
        ...
        create_a(results);
        ...
    }
});
// Query 2 Subprojects
var queryTask_b = new QueryTask();
queryTask_a.execute(query_a_obj,
    function (results) {
        ...
        create_b(results);
        ...
    }
});

Теперь я хочу вызвать выпадающее меню Projects on('change') на основе value. Когда это будет завершено, я хочу сделать то же самое для выпадающего списка подпроектов. Например:

var info_proj_name = "project_a";
var subproj_name = "subproject_b"
dijit.byId('projectSelect').set("value", info_proj_name);
dijit.byId('subprojectSelect').set("value", subproj_name);     

Проблема в том, что на данный момент dijit.byId('projectSelect') может / не может существовать в dom, .set может / не может быть функцией, и т.д. c. Похоже, что если я медленно запустил его, как указано выше, в Chrome Devtools, это работает, но когда я позволяю приложению работать как есть, возникает задержка во времени, когда выпадающие списки создаются и заполняются запросом, и когда dijit.byId('projectSelect').set("value", info_proj_name); вызывается. Так как я уже использую Dojo/Dijit, я пытаюсь применить функциональность promise/callback, такую ​​как Deferred, чтобы выполнить все по порядку:

1) query a (get list of items for project dropdown)
2) call create_a function (create project dropdown, trigger subproject process)
3) query b (get list of items for subproject dropdown)
4) call create_b function (create subproject dropdown)
5) select an option from projects dropdown (triggers subprojects query and subrprojects dropdown)
6) select and option from subprojects dropdown (triggers subprojects on(change) event)

Я несколько смущен тем, как я могу применить что-то вроде это, чтобы связать эти вещи вместе. Любые предложения о том, как настроить это в общем смысле?

1 Ответ

1 голос
/ 04 апреля 2020

Чтобы избежать перестройки всей архитектуры, вы можете попробовать dojo / ready (см. здесь для документации):

ready(function(){
    dijit.byId('projectSelect').set("value", info_proj_name);
    ready(function(){
        dijit.byId('subprojectSelect').set("value", subproj_name); 
    });
});

Если это не сработает, следующая возможность - setTimeout:

setTimeout(function(){
    dijit.byId('projectSelect').set("value", info_proj_name);
    setTimeout(function(){
        dijit.byId('subprojectSelect').set("value", subproj_name); 
    }, timeout1);
}, timeout2);

, затем выполните работу с угадыванием для timeout1 и timeout2 и, прежде всего, скрестите пальцы, если эти операторы должны ждать ответа сервера.

Теперь, конечно, ре-архитектура поможет. Я бы начал с перемещения вызова в queryTask_b.execute внутри обратного вызова queryTask_a.execute и после оператора create_a, который учитывает ваш 1, 2, 3, 4 порядок выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...