【问题标题】:JavaScript Deferred Object - Running Two Asynchonous Request After the PromiseJavaScript 延迟对象 - 在 Promise 之后运行两个异步请求
【发布时间】:2018-11-07 00:34:34
【问题描述】:

我有一个包含三个选择选项的菜单。第一个选择是其余两个的驱动程序;他们需要第一个菜单项的值来填充。但是,它们是并行的——这两者都不相互依赖,因此它们的 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));

【问题讨论】:

    标签: javascript jquery-deferred deferred


    【解决方案1】:

    你应该使用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));
    

    【讨论】:

    • .then(function ([college, term]) { buildMenu('college', college); buildMenu('term', term); }) 是使用destructuring syntax的好地方
    • 为了避免混淆,jQuery 3.0 之前不支持将 jQuery.DeferredPromise 混合使用
    • @Neverever:谢谢,这对更好地理解 JQuery Deferred 对象很有帮助!
    • @Patrick Roberts:感谢您的来信。我将其合并到我的解决方案中。
    【解决方案2】:

    您的所有三个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
     });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-01
      • 2020-09-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多