Отложенный объект JavaScript - выполнение двух асинхронных запросов после обещания - PullRequest
0 голосов
/ 07 ноября 2018

У меня есть меню с тремя вариантами выбора. Первый выбор - это драйвер для оставшихся двух; они требуют значения первого пункта меню для заполнения. Однако они параллельны - ни один из этих двух не зависит друг от друга, поэтому их вызовы ajax могут выполняться параллельно.

Мой текущий пользователь выполняет вызов ajax для первого меню, а затем использует метод .then () для вызова одного из следующих меню, а другой .then () для последнего меню. Это не очень эффективно. Я пытаюсь выяснить, как заставить оба вызова подменю работать под одним .then ()

    //Get campus list and build menu
    $.getJSON(apiURL)
    .then( function(campusdata) {
        buildMenu('campus', campusdata);
        return $.getJSON(apiURL + '/colleges/' + $campus.val());
    })

    //Build college menu
    .then(function(collegedata) {
        buildMenu('college', collegedata);
        return $.getJSON(apiURL + '/campus-year-terms/' + $campus.val());
    })

    //Build academic terms submenu
    .then(function(termdata){
       buildMenu('term', termdata);
    })

    .done(function(){
        <other stuff that can really be completeduntil menus are populated>
    })

    .fail(console.log.bind(console));

Ответы [ 2 ]

0 голосов
/ 07 ноября 2018

Похоже, что все три ваших getJSON() вызова независимы (не зависят друг от друга, если $campus не является побочным эффектом первого buildMenu()). Это должно означать, что вы можете выполнять их все одновременно (параллельно), собирать все результаты и создавать меню сразу:

Promise.all([
    $.getJSON(apiURL),
    $.getJSON(apiURL + '/colleges/' + $campus.val()),
    $.getJSON(apiURL + '/campus-year-terms/' + $campus.val())
]).then(function([campusData, collegeData, termData]) {
    buildMenu('campus', campusdata);
    buildMenu('college', collegedata);
    buildMenu('term', termdata);
    // other code here after all menus are done
}).catch(function(err) {
    // handle error here
});

Или, если вам нужна поддержка браузера, не включающая деструктуризацию массива:

Promise.all([
    $.getJSON(apiURL),
    $.getJSON(apiURL + '/colleges/' + $campus.val()),
    $.getJSON(apiURL + '/campus-year-terms/' + $campus.val())
]).then(function(results) {
    buildMenu('campus', results[0]);
    buildMenu('college', results[1]);
    buildMenu('term', results[2]);
    // other code here after all menus are done
}).catch(function(err) {
    // handle error here
});

Если по какой-то причине $campus.val() зависит от первого вызова API, вам придется изменить его на следующее:

$.getJSON(apiURL).then(function(campusdata) {
    buildMenu('campus', campusdata);
    return Promise.all([
        $.getJSON(apiURL + '/colleges/' + $campus.val()),
        $.getJSON(apiURL + '/campus-year-terms/' + $campus.val())
    ]).then(function(results) {
        buildMenu('college', results[0]);
        buildMenu('term', results[1]);
        // other code here after all menus are done
    });
 }).catch(function(err) {
        // handle error here
 });
0 голосов
/ 07 ноября 2018

Вы должны использовать Promise.all

$.getJSON(apiURL)
.then( function(campusdata) {
    buildMenu('campus', campusdata);

    // use `Promise.all` to run two parallel ajax calls
    return Promise.all([
        $.getJSON(apiURL + '/colleges/' + $campus.val()),
        $.getJSON(apiURL + '/campus-year-terms/' + $campus.val())
    ]);
})

// result will be an array containing the json data from both calls
.then(function(result) {
    buildMenu('college', result[0]);
    buildMenu('term', result[1]);
})
.done(function(){
    <other stuff that can really be completeduntil menus are populated>
})

.fail(console.log.bind(console));
...