关于javascript:eslintplugin初体验定时器检测

44次阅读

共计 2617 个字符,预计需要花费 7 分钟才能阅读完成。

前言

很久没有写文章了,次要是没什么值得写的。
打工人天天搬砖,的确写无可写。
直到最近整顿团队标准,总算遇到了值得一写的内容。

遇见

整顿代码的时候,在我的项目中发现了很多定时器,比方:

setInterval(() => {this.getData()
}, 1e4)

这是定时轮询,更新数据的一段代码。翻了翻历史记录,是个新来的实习生写的。
因为没有把定时器存储起来,天然不可能勾销。
所以每次关上这个组件,就会产生一个定时器,如果用户屡次进入这个页面,那就很蹩脚了。

解决

全局查找 setInterval 一个个解决,其实问题也不大。我找了下,大略也就百十来个 setInterval!当然不会是每个都须要解决,然而一一查看解决,也有点燥人。
所以最初的解决方案是,通过 eslint 查找,而后对立解决。最次要的是,防止前面的代码持续呈现这种状况。

尝试

网上有很多现成的 demo,然而信息大多比拟散乱。比方有的 demo 版本比拟低,尽管能够运行,我的项目援用就不行。
有的 demo 不残缺,还须要本人补全。
当然,最次要的还是,我压根没理解过 eslint 的运行规定……
不得已,查资料,debugger,一步步后退。

AST 形象语法树

eslint 怎么运行?这就不得不接触到 AST 的概念。
代码拆解,从语句,语句块,表达式,函数,申明,等等概念,全副拆解到树形构造上,一一映射。
在这篇文章上曾经讲得比拟粗疏:AST 形象语法树.

eslint-plugin

eslint-plugin 有本人的标准。
咱们要开发一个插件,就必须遵循标准。
恰好是在这个标准上卡了我比拟长时间——整整一天。
我找了相干的 demo,本人写了一个例子,查找没有存储的定时器。很快例子就写好了,也通过测试。
于是我就开开心心的发到 npm,而后在我的项目中援用,运行代码,所有都很顺利。
然而什么提醒都没有!!!
黑人脸!!!

debugger

在 node_modules 中调试代码,持续运行。
然而更加奇怪,连我打的 debugger 都没执行。
一直批改,再运行,还是没有。
如此数次下来,慢慢狐疑人生。
难道是 .eslintrc.js 配置不对?
天知道,我压根没读过 .eslintrc.js 的配置,我只是一个搬运工。
好吧,先把 .eslintrc.js 读一遍。
原来,我真的没有配对 .eslintrc.js。。。
一番折腾之后,终于有了提醒 definition for rule 'no-record-time' was not found
好吧,no-record-time是我引入的 npm 包,持续折腾。
因为开发方式的起因,我须要用以下形式引入:

  plugins: ["no-record-time",],
  rules: {'no-record-time/no-record-time': 2},

解决了这步,信念大增。

而后,我又发现了一个命令 npm run lint --debug,这个命令能够间接把 eslint 运行的后果打印进去,我终于不必改一句代码就重启一次编辑器,锦上添花。
然而,后果很奇怪,我写的规定忽然不失效了。
怎么肥事?

Parser API

开始我用的是 Program:exit 查找,这是 Parser API 提供的一个对象,eslint 的标准能够返回这个属性,执行所有 Program 节点的代码遍历。
在测试中,我写的规定能够被很好的运行。然而到了我的项目中,就不行了。
起因未知。
然而我发现了一个更好的对象——ExpressionStatement
这是一个表达式语句对象。
如上文:

setInterval(() => {this.getData()
}, 1e4)

这就是一个表达式语句。
如果这样就不是表达式了:

let timer = setInterval(() => {this.getData()
}, 1e4)

这是一个申明赋值语句。
所以能够间接查找表达式语句对象。
一通操作,把节点对象打印之后,发现了法则。
node.expression.callee.name这个属性能够读取表达式的函数名,当然,前提是必须有 node.expression.callee
那么判断条件就很容易了:

function getSetInterval(node) {if (node.expression.callee && node.expression.callee.name === 'setInterval') {return false}
  if (node.expression.callee && node.expression.callee.name === 'setTimeout') {return false}
  return true
}

这样就能够找到没存储的定时器了。

残缺代码

/**
 * @fileoverview Rule to flag timer didn't record.
 * @author 陈其文 <jianwang19@sina.com>
 * @copyright 2021-01 All rights reserved.
 */
"use strict";

module.exports = {
  meta: {
    type: "problem",

    docs: {
      description: "定时器检测",
      category: "ExpressionStatement",
      recommended: true,
    },

    schema: []},
  create: function (context) {function getSetInterval(node) {if (node.expression.callee && node.expression.callee.name === 'setInterval') {return false}
      if (node.expression.callee && node.expression.callee.name === 'setTimeout') {return false}
      return true
    }
    return {ExpressionStatement(node){let state = getSetInterval(node)
        if (!state) {context.report(node, '{{ name}} timer didn\'t record', {name: node.expression.callee.name});
        }
      },
    };
  },
};

最初发现,其实很简略。
还没通过残缺测试,兴许存在 bug。
但究竟是迈出了一大步。
git 仓库如下:eslint-plugin-no-record-time

正文完
 0