【问题标题】:ReactJS - JavaScript: Filter function does not work properlyReactJS - JavaScript:过滤功能无法正常工作
【发布时间】:2020-02-27 15:05:17
【问题描述】:

我正在使用AISHub APIs 构建一个船只可视化器。在查询 API 后,我能够获得一个包含数千个容器的 json 文件,但我只过滤我感兴趣的容器,并将它们注入到网页上的表格中。 API 提供以下文件:[NAME, MMSI, LONGITUDE, LATITUDE, others...]。我用于过滤的最重要参数是:NAMEMMSI(虽然可能有多个容器具有相同的NAME,但不能有两个容器具有相同的MMSI 编号,因为它是唯一的)。

问题我的问题是filter 函数似乎没有正确的行为。 事实上,它不会针对特定的NAME 和/或MMSI 进行唯一过滤,我最终会拥有多个具有相同NAME 和不同MMSI 的容器。还有应该出现的容器,它没有,尽管我为该特定容器硬编码了NAMEMMSI。 这是无法解释的,因为我将这些数字硬编码为专门过滤。

在我用于过滤搜索的代码下方:

var express = require('express');
var router = express.Router();
var axios = require('axios');
const NodeCache = require('node-cache');
const myCache = new NodeCache();

let hitCount = 0;

/* GET home page. */
router.get('/', function(req, res, next) {
    res.render('index', { title: 'Express' });
});

const mmsiOfInterest = [
    '367029520', // ok -> MICHIGAN
    '366909730', // ok -> JP BOISSEAU
    '367128570', // ok -> DELAWARE BAY
    '366744010', // ok -> ATLANTIC SALVOR
    // Other MMSI numbers .....
];


const shipNamesOfInterest = [
    'MICHIGAN',
    'JP BOISSEAU',
    'DELAWARE BAY',
    'ATLANTIC SALVOR',
    // Other NAMES....
]

router.get('/hello', async function(req, res, next) {
    const allData = myCache.get('allData');

    if (!allData) {
        hitCount++;
        console.log(`hit ${hitCount} number of times`);
        const { data } = await axios.get(
            'http://data.aishub.net/ws.php?username=MY_KEY&format=1&output=json&compress=0&latmin=11.42&latmax=58.20&lonmin=-134.09&lonmax=-52.62'
        );

        const [ metaData, ships ] = data;
        console.log(data);

        const shipsOfInterest = ships.filter(
            (ship) => mmsiOfInterest.includes(ship.MMSI) || shipNamesOfInterest.includes(ship.NAME)
        );
        myCache.set('allData', shipsOfInterest, 70);
        res.send(data);
        return;
    }

    console.log('this is the data:', allData);
    res.send(allData);
});

module.exports = router;

同样低于来自 API 的典型 JSON 响应:

{"MMSI":225342000,"TIME":"2020-01-26 01:45:48 GMT","LONGITUDE":1.43912,"LATITUDE":38.91523,"COG":339.9,"SOG":0,"HEADING":297,"ROT":0,"NAVSTAT":0,"IMO":9822449,"NAME":"ILLETAS JET","CALLSIGN":"EAVX","TYPE":40,"A":4,"B":25,"C":4,"D":4,"DRAUGHT":0,"DEST":"IBIZA","ETA":"00-00 00:00"}

到目前为止我做了什么:

1) 我尝试了与filter 函数的不同组合,并尝试按MMSI 进行过滤,这应该对每艘船都是唯一的,但我最终还是得到了具有相同NAME 和不同@ 的船987654341@(尽管我硬编码了MMSI...我不明白):

const shipsOfInterest = ships.filter(
                (ship) => mmsiOfInterest.includes(ship.MMSI)
            );

在我尝试通过NAME 过滤后,但这也不起作用:

const shipsOfInterest = ships.filter(
                (ship) => shipNamesOfInterest.includes(ship.NAME)
            );

编辑 2

router.get('/hello', async function(req, res, next) {
    //
    const allData = myCache.get('allData');

    if (!allData) {
        hitCount++;
        console.log(`hit ${hitCount} number of times`);
        const { data } = await axios.get(
            'http://data.aishub.net/ws.php?username=KEY&format=1&output=json&compress=0&latmin=11.42&latmax=58.20&lonmin=-134.09&lonmax=-52.62'
        );

        // console.log(data);
        const { metaData, ships } = data;
        const set = new Set();
        const shipsOfInterest = ships.filter((ship) => {
            if (set.has(ship.MMSI)) return false;
            set.add(ship.MMSI);
            return true;
        });
        myCache.set('allData', shipsOfInterest, 70);
        res.send(data);
        return;
    }

    console.log('this is the data:', allData);
    res.send(allData);
});

module.exports = router;

下面的错误:

我不知道如果以不同的方式组织filter 函数是否可以获得更好的结果。我认为这可能是组织搜索的一种非常好的方法,但不明白它不起作用的地方。 感谢您指出解决此问题的正确方向。

【问题讨论】:

  • 通过“对 MMSI 进行硬编码,您是说类似以下代码的内容返回带有多个 MMSI 值的内容?const shipsOfInterest = ships.filter(ship => ship.MMSI === '367029520' );
  • 另外,您能否提供一个 API 返回的 JSON 的小示例?他们的网站只显示了一个 XML 格式的示例。
  • 我没有直接尝试,因为我对关联图进行了硬编码:mmsiOfInterestshipNamesOfInterest 完全匹配。不过我可以试试。另外是的,让我发布一个JSON 格式的典型示例。
  • 好的,发布JSON回复
  • 出现新错误时,如果 API 返回错误代码,您应该尝试将 get 包装在“try/catch”块中以停止执行。

标签: javascript json reactjs ais


【解决方案1】:

if 语句的末尾你做res.send(data),这基本上是你从API 收到的数据。相反,您需要res.send(shipsOfInterest);另外,将mmsiOfInterest 列表的格式从字符串更改为数字,因为您从 API 接收数字。

【讨论】:

    【解决方案2】:

    我猜你在使用速记赋值时犯了错误。使用 {} 而不是 []。

    代替:

      const [ metaData, ships ] = data;
    

    尝试:

      const { metaData, ships } = data;
    

    【讨论】:

    • 感谢您阅读问题。不幸的是,如果我根据您的建议进行切换,则没有任何效果,并且该功能甚至无法过滤任何容器。我想这样做,但直到现在才尝试过。
    • 好的,我也更新了带有您建议的问题。 EDIT 2 带有提供的代码和错误的print screen。有用吗?
    【解决方案3】:

    所以,据我了解,过滤列表包含具有唯一 MMSI 值的记录。所以,你需要做的是:

    const uniqueMMSI = new Set();
    const shipsOfInterest = ships.filter(
      (ship) => {
        if (set.has(ship.MMSI)) return false;
        set.add(ship.MMSI);
        return true;
      }
    );
    

    希望我理解你的问题:)

    【讨论】:

    • 感谢您阅读这个问题。我尝试了您的解决方案,它在开始过滤时部分工作,但它停止抛出:(node:16461) UnhandledPromiseRejectionWarning: ReferenceError: set is not defined
    • 对不起,我打错了,请将uniqueMMSI重命名为set
    • 别担心,你是说这个吗:const uniqueMMSI = new set();
    • 好的,小进步。它开始过滤,但停止抛出此错误:(node:17284) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'filter' of undefined。我将打印错误屏幕。
    • @Flavin 解释了为什么这里未定义 stackoverflow.com/a/60436602/5847921
    【解决方案4】:

    看起来 MMSI 是以数值形式出现的,而您的比较数组包含字符串。使用整数数组进行比较怎么样?

    const mmsiOfInterest = [
        367029520,
        366909730, 
        367128570, 
        366744010, 
        // Other MMSI numbers .....
    ];
    

    【讨论】:

    • 那是我没有尝试过的另一个选项。我刚试了一下,它开始过滤,但因错误而停止:(node:17733) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'filter' of undefined
    • 好的,我更新了问题。 EDIT 2 提供了建议和错误的print screen。有用吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-04
    • 1970-01-01
    • 1970-01-01
    • 2015-07-17
    • 2018-07-29
    • 2017-09-23
    相关资源
    最近更新 更多