【问题标题】:Promises Sequencing承诺测序
【发布时间】:2019-10-23 12:50:47
【问题描述】:

在这个函数中,我试图运行 2 个不同的 ajax 请求(3 个选项,根据 if 语句只有 2 个会运行)。 addDep()addCust() 函数都包含一个 ajax 请求并被发送一个 url。但是,我需要该 ajax 函数在运行后调用 .then 函数中的代码之前运行和完成。现在代码运行但具有空值,因为它没有从 ajax 函数返回 data1 或 data2。我该如何解决这个问题?

function builder(){
    var beforeDate = dateConv(document.getElementById('Before').value);
    var afterDate = dateConv(document.getElementById('After').value);

    var url = "http://localhost:8181/GRAIN/grain_map?start="
    url += afterDate;
    url += "&end=";
    url += beforeDate;
    url += "&attributes=DATE-SHIPPED+DESTINATION-NAME+DESTINATION";

    ajaxReq(url).then(function (jsonString) {
        for (i=0; i < jsonString.grain_map.length; i++){
            destinationArray.push(jsonString.grain_map[i].DESTINATION);
        }

        for (i = 0; i < destinationArray.length; i++){
            if (destinationArray[i] == ""){
                continue;
            }
            if (destinationArray[i].length == 3 || destinationArray[i].length == 2){
                var destCode = destinationArray[i];
                addDep(destCode).then(function (data1) {
                    var address = "";
                    var depArray = data1.dep_address[0].ADDRESS;
                    for(i = 0; i < depArray.length; i++){
                        address += data1.dep_address[0].ADDRESS[i] + " ";
                    }
                    addressArray.push(address);
                }).catch(function (err) {
                    console.error(err);
                });

            }else if (destinationArray[i].length == 6){
                var destCode = destinationArray[i];
                addCust(destCode).then(function (data2) {
                    var address = "";
                    var depArray = data2.customer_address[0].ADDRESS;
                    for(i = 0; i < depArray.length; i++){
                        address += data2.customer_address[0].ADDRESS[i] + " ";
                    }
                    addressArray.push(address);
                }).catch(function (err) {
                    console.error(err);
                });
            }
        }
    }).catch(function (err) {
        console.error(err);
    });
}

【问题讨论】:

标签: javascript ajax asynchronous promise


【解决方案1】:

目前情况:

  • builder() 返回 undefined - 它应该返回 Promise。
  • 外部 then 的回调返回 undefined - 它应该返回 Promise。
  • 两个内部 then 回调返回 undefined - 它们可以(并且应该)返回 String。
  • addDep()addCust() 返回的内部 Promise 未聚合 - 没有 Promise.all()
  • 有两个神秘的、未声明的数组,destinationArrayaddressArray,这让我有些猜测。

数组方法.map().filter().join()可以简化代码

function builder() {
    var beforeDate = dateConv(document.getElementById('Before').value);
    var afterDate = dateConv(document.getElementById('After').value);
    var url = `http://localhost:8181/GRAIN/grain_map?start=${afterDate}&end=${beforeDate}&attributes=DATE-SHIPPED+DESTINATION-NAME+DESTINATION`;
    return ajaxReq(url)
//  ^^^^^^
    .then(jsonString => {
        var promises = jsonString.grain_map
        .map(item => {
            var destcode = item.DESTINATION || '';
            switch(destCode.length) {
                case 2:
                case 3:
                    return addDep(destCode)
                //  ^^^^^^
                    .then(data => data.dep_address[0].ADDRESS.join(' '))
                    .catch(error => `addDep: ${destCode}: ${error.message}`); // inject message in place of missing address
                break;
                case 6:
                    return addCust(destCode)
                //  ^^^^^^
                    .then(data => data.customer_address[0].ADDRESS.join(' '))
                    .catch(error => `addCust: ${destCode}: ${error.message}`); // inject message in place of missing address
                break;
                default:
                    return null;
                //  ^^^^^^
            }
        })
        .filter(p => !!p); // filter out any nulls leaving just Promises
        return Promise.all(promises);
    });
}

返回调用者...

builder()
.then(addressArray => {
    // do something with addressArray.
})
.catch(err => {
    console.error(err);
    throw error; // unless this promise chain is at the topmost level of an event thread.
});

注意事项:

  • 问题的中间 destinationArray 完全消失了 - 它(可能)从来没有必要。
  • Arrow functions 用于紧凑。
  • 您在这些 catch 处理程序中执行的操作完全取决于您想要什么。如上所述,将注入一条错误消息来代替每个丢失的地址。您也可以选择重新抛出错误,并允许 Promise.all(promises) 返回的 Promise 在遇到第一个错误时遵循其错误路径。
  • addressArray 现在由 builder() 返回的 Promise 传递。
  • switch/case 结构不是绝对必要的,但可以使代码更简洁 (恕我直言)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-07
    • 2017-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-17
    • 2020-07-30
    相关资源
    最近更新 更多