首页 > 解决方案 > 在 Node/Express 中,如何使用 csv-to-array 匹配或比较嵌套承诺中的值

问题描述

我有一个使用 AJAX 调用的 Node/Express 部分,并且应该在进行 2 次后续 API 调用后将状态更新发送回视图。此工作流依赖 csv-to-array 模块来读取 ship-orders.csv 文件,并确定是否已经发生了第二个 API 调用(POST 到 Shipments)。应该通过将 csv 文件中的 OrderNumber 与从 FindOrders 端点(第一个 API)返回的 OrderNumber 匹配来执行此操作。

问题是我正在创建 2 个订单号数组进行比较,但是将第一组订单号与第二组匹配总是返回 true 或总是返回 false,并且它应该非常清楚地显示第一个记录为“true” csv,并且每个其他都为“假”。

在进入大部分代码之前,这是将 csv 文件读入数组的承诺:

csv 到数组:

var csvShipPromise = new Promise(function(resolve, reject){

    var csvColumns = ['ChannelName', 'OrderNumber', 'LineNumber', 'WarehouseCode', 'Qty', 'Carrier', 'TrackingNumber', 'Shipdate', 'ShipMethod'];
    var csvShipArr;

    var csvArr;
    csvArray({
        file: shipLog,
        columns: csvColumns
    }, function(err, array){
        csvShipArr = array;
        resolve(csvShipArr);
    });
});

接下来,我有一个很长的承诺,当对部分的请求发出时就会执行。记录的 OrderNumbers 和需要发布到 Shipments 的 OrderNumbers 之间的比较是第 5 个“then”块(并且在下面的代码中进行了注释)。

router.get 和链式承诺:

router.get('/', function(req, res, next) {

findPromise.then(function(findData){
    //Properly format xml string
    var foundData = replaceAll(findData, '&lt;', '<');
        foundData = replaceAll(foundData, '&gt;', '>');
    return foundData;  
}).then(function(foundData){
    //Parse xml to JSON and stringify
    var parsedFound;
    parseString(foundData, function(err, result){  //uses an xml to json module
       parsedFound = JSON.stringify(result); 
    });
    return(parsedFound);
}).then(function(parsedStr){
    //Parse JSON and return an array of objects
    var parsedJson = JSON.parse(parsedStr);
    var orders = parsedJson['soap:Envelope']['soap:Body'][0]['FindOrders'][0]['orders'][0]['order'];
    return orders;
}).then(function(orders){
    //Get only orders with a tracking number.
    var trackArray = [];
    var ord;
    for(ord in orders){
        var postObj = orders[ord];
        if(postObj.TrackingNumber[0].length > 1){
            trackArray.push(postObj);
        }
    }
    return trackArray;  //array of orders that contain tracking numbers
}).then(function(trackArray){

    /**** This is the block that is causing problems. *****/

    var tItm;

    var loggedOrders = [];
    for(tItm in trackArray){
        var alreadyLogged = false;
        var trackedItm = trackArray[tItm];
        var trackedOrderNum = trackedItm.ReferenceNum;
        csvShipPromise.then(function(csvOrders){
            var csv;
            var loggedOrderArr = [];
            for (csv in csvOrders){
                var csvItm = csvOrders[csv];
                var csvOrderNum = csvItm.OrderNumber; //gets the OrderNumber as expected
                loggedOrderArr.push(csvOrderNum);
            }
            return loggedOrderArr; //Return a simple array of all OrderNumbers
        }).then(function(loggedOrderArr){
            console.log(loggedOrderArr);
            console.log(trackedOrderNum);
            var ord;
            for (ord in loggedOrderArr){
                if(trackedOrderNum == loggedOrderArr[ord]){
                    console.log('found');
                    alreadyLogged = true;
                }
                else {
                    console.log('not found');
                    alreadyLogged = false;
                }
            }
            return loggedOrderArr; //Simply returning this value because the alreadyLogged test isn't working.
        });

        /*  Here is where the test fails.
          It shouldn't, because there are, say, 4 OrderNumbers in the result of the first API call,
          and only 1 Order number logged in the CSV.
          So it should be true once, and false 3 times.
          But it is true all the time.
        */
        if(alreadyLogged){
            console.log('found');  //Always logs true/found.
        } else {
            console.log('not found');
        }
    }
    return trackArray; //Just passing the array to the view, for now.
}).then(function(obj){
    res.send(obj);
    return(obj);
}).catch(function(err){
    console.log(err);
});
});

当我 console.log 记录 trackArray 和 loggedOrderArr 的值时,我看到 4 个值的数组和 1 个值的数组之间应该有一个交集,但由于某种原因,比较if(trackedOrderNumber == loggedOrderArr[ord])不起作用。

标签: node.jsajaxcsvexpresspromise

解决方案


好吧,老实说,你的代码让我眼前一亮。但据我所知,出现了一些事情:

  • 将 varalreadyLogged = false;移到循环之前;
  • alreadyLogged = false;然后在if(alreadyLogged)声明之后添加

我认为这与范围有关。您基本上是在检查尚未更改的 var 的 bool 值,因为您的承诺尚未解决if(alreadyLogged)

我可以建议一种不同的方法吗?

为什么不使用 array.indexOf() ?

假设你有两个数组来比较 arrA 和 arrB; 您可以像这样查看项目是否存在:

var index = arrA.indexOf(arrB[0]); 
if(index == -1){
   console.log('No Match');
}
else{
   console.log('Match found');
}

不需要任何预设标志来查看一个数组是否包含一个元素。

希望能帮助到你。

更多上下文:

var index = loggedOrderArray.indexOf(trackedOrderNum); 
if(index == -1){
   console.log('No Match');
   // -1 basicaly means that there is not instance of trackedOrderNum in loggedOrderArray
}
else{
   console.log('Match found');
}

推荐阅读