Superset Filter box报错Cannot read property ‘map’ of undefined的解决方案
最近在用superset做数据分析时,用到了 Filter box筛选框,筛选其他的类型没什么问题,只要是日期有关的筛选,所有的筛选框都会消失,我安装superset是用pip安装的,版本号是0.28.1。如图报错:
首先想到的解决方案就是去github查找issues,果真很多同学都遇到了这个问题。
然后也找了两个解决办法:
https://github.com/apache/incubator-superset/commit/912c6f623159be69007cc9ee38b10e8adc7778ce
https://github.com/lyft/incubator-superset/commit/57410671fb90aa86433274eb6dd644b134b92dbe
但是解决的都是源码的问题,pip安装的都是编译好的,而且代码都不一样。
最终我通过看源代码,一个个打断点将这个问题解决了。
首先看文件
/usr/local/lib/python3.7/site-packages/superset/static/assets/dist/filter_box.885b5b9fd31f4d3caa48.chunk.js
这个文件代码是压缩了的,我们先将代码解压,发现我问题出现在这里:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | { key: "renderFilters", value: function() { return function() { var e = this , t = this.props , n = t.filtersFields , r = t.filtersChoices , a = this.state.selectedValues; return Object.keys(a).filter(function(e) { return !(a.hasOwnProperty(e) && e in r) }).forEach(function(e) { var t = r[e] , n = new Set(t.map(function(e) { return e.id })); a[e].filter(function(e) { return !n.has(e) }).forEach(function(n) { t.unshift({ filter: e, id: n, text: n, metric: 0 }) }) }), n.map(function(t) { var n = t.key , u = t.label , s = r[n] , c = Math.max.apply(Math, function(e) { if (Array.isArray(e)) { for (var t = 0, n = Array(e.length); t < e.length; t++) n[t] = e[t]; return n } return Array.from(e) }(s.map(function(e) { return e.metric }))); return o.default.createElement("div", { key: n, className: "m-b-5" }, u, o.default.createElement(p.default, { placeholder: (0, v.t)("Select [%s]", u), key: n, multi: !0, value: a[n], options: s.map(function(e) { var t = Math.round(e.metric / c * 100) , n = { backgroundImage: "linear-gradient(to right, lightgrey, lightgrey " + t + "%, rgba(0,0,0,0) " + t + "%", padding: "2px 5px" }; return { value: e.id, label: e.id, style: n } }), onChange: function() { for (var t = arguments.length, r = Array(t), o = 0; o < t; o++) r[o] = arguments[o]; e.changeFilter.apply(e, [n].concat(r)) }, selectComponent: l.Creatable, selectWrap: i.default, optionRenderer: (0, h.default)(function(e) { return e.label }) })) }) } }() }, |
通过看代码逻辑var t = r[e]是一个undifined,因为上面的过滤return !(a.hasOwnProperty(e) && e in r),可以判断出e不是r里面,所有r[e]没有,而下面的t.map必须要求t是一个数组,所以这里代码报错了。
首先我去看了pip官网,发现有两个预发布版本,我直接看看这里的代码有没有修复,发现是有变化的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | key: "renderFilters", value: function() { return function() { var e = this, t = this.props, n = t.filtersFields, r = t.filtersChoices, a = this.state.selectedValues; return Object.keys(a).filter(function(e) { return a.hasOwnProperty(e) && e in r }).forEach(function(e) { var t = r[e] || [], n = new Set(t.map(function(e) { return e.id })); (Array.isArray(a[e]) ? a[e] : [a[e]]).filter(function(e) { return !n.has(e) }).forEach(function(n) { t.unshift({ filter: e, id: n, text: n, metric: 0 }) }) |
这里的筛选条件变了,return a.hasOwnProperty(e) && e in r,以前是非,现在与。
直接替换这里的代码,报错,不行。
那么我直接安装0.29版本呢?看看修复完成没?
1 | pip install superset==0.29.0rc7 |
安装完成,运行superset runserver -d
报错,说是flask1.0版本废弃了命令,试用flask run 什么的。
居然运行不起来,然后我查了一下superset runserver -help
试着不用-d参数superset runserver居然成功了,真是奇怪了。
然后运行 127.0.0.1:8088,发现搜索框是好的。看来新版本是解决了这个问题。
当然如果线上运行的是0.28.1版本的,不想升级怎么办呢。
继续调试bug。
看下我打的断点输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | var e = this, t = this.props, n = t.filtersFields, r = t.filtersChoices, a = this.state.selectedValues; console.log('第一步:',e) console.log('第二步:',t) console.log('第三步:',n) console.log('第四步:',r) console.log('第五步:',a) return Object.keys(a).filter(function(e) { console.log('第1步:',e) console.log('第2步:',a.hasOwnProperty(e)) console.log('第3步:',e in r) return !(a.hasOwnProperty(e) && e in r) }).forEach(function(e) { var t = r[e]; console.log('第七步:',t) console.log('第八步:',e) |
那么我将t重新定义一下r[e] || [],然后发现a[e].filter这里报错,filter函数也需要是一个数组,可是a[e]是一个值,我们把它变成一个数组,Array.isArray(a[e]) ? a[e] : [a[e]]。这里改好以后,这里n.map也报错,原来这里的n已经被上面的forEach的回调函数改了,这个n应该是上面n = t.filtersFields的值,这里我们改一下将n重新定义一下,问题解决了。
说到底还是类型的问题,总共也就改了两个地方。
看看最新代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | var t = r[e] || [], n = new Set(t.map(function(e) { return e.id })); (Array.isArray(a[e]) ? a[e] : [a[e]]).filter(function(e) { return !n.has(e) }).forEach(function(n) { t.unshift({ filter: e, id: n, text: n, metric: 0 }) }) |
最后,再将代码压缩下,传到服务器,问题解决了。
这里我把压缩的代码放到这里,供大家直接下载。
文章不错支持一下吧
文章不错支持一下,非常喜欢
文章不错支持一下吧
文章不错支持一下吧
文章不错支持一下吧
非常感谢!替换完之后重新登录清除下浏览器缓存就可以用了!
能帮助到您真是开心!