Chrome 插件 onRequestFinished addListener removeListener 事件踩坑指南

chrome.devtools.network.onRequestFinished 事件踩坑指南

  1. 回调函数无法使用变更变量坑
  2. addListener removeListener 使用坑

回调函数无法使用变更变量坑

chrome.devtools.network.onRequestFinished.addListener 传入的回调处理函数发生变化后不生效,如下写法是有问题的

let listenering = false

const Component: React.FC = () => {
    const [grabing, setGrabing] = useState<boolean>(false);
    const [filterKeyList, setFilterKeyList] = useState<FilterKeyList[]>();

    const activeFilter = useMemo(() => filterKeyList.filter(item => item.switch && item.value), [filterKeyList]);

    const handleListener = useCallback((details: RequestFinished) => {
        try {
            const {
                _resourceType,
                request: { method },
            } = details;

            if (activeFilter?.length === 0 || !grabing || _resourceType !== 'xhr') return;

            if (activeFilter?.some(item => method === item.method)) {
                details.getContent(content => console.log('content=', content));
            }
        } catch (e) {
            console.log('糟糕,出错了!!!');
        }
    }, [grabing, activeFilter]);

    useEffect(() => {
        if(!listenering){
            chrome.devtools.network.onRequestFinished.addListener(handleListener);
            listenering = true;
        }
    }, [handleListener]);

    return (
        <h1>demo</h1>
    );
};

问题1:addListener 的回调处理函数 handleListener 不随着 grabing, activeFilter 变化
原因:回调触发时对应的值是当时 addListener 实际的值,不随着外部变量变化而变化
解决:当 activeFilter 和 grabing 改变时需要调用 addListener 重新监听

当需要重新监听时,就需要对之前的 addListener 进行 removeListener 处理,否则会产生多个监听进程,就有了下边的问题2

addListener removeListener 使用坑

问题2:调用 removeListener 无法取消监听
原因:chrome.devtools.network.onRequestFinished.removeListener() 需要一个参数,不是直接执行就取消监听了,且参数需要和当初 addListener 定义的同一个回调函数,因为 grabing, activeFilter 变化后,handleListener 就是一个新的函数了,所以无法取消监听
方案:将 addListener 使用的 handleListener 通过 useRef 存起来,每次需要重新监听的时候先把上一个移除,再次发起监听的时候将当时使用的 handleListener 再次存入 useRef 即可解决,代码如下:

const Component: React.FC = () => {
    const [grabing, setGrabing] = useState<boolean>(false);
    const [filterKeyList, setFilterKeyList] = useState<FilterKeyList[]>();

    const handleListenerRef = useRef<(details: RequestFinished) => void>();

    const activeFilter = useMemo(() => filterKeyList.filter(item => item.switch && item.value), [filterKeyList]);

    const handleListener = useCallback((details: RequestFinished, grabing: boolean, activeFilter: FilterKeyList[]) => {
        try {
            const {
                _resourceType,
                request: { method },
            } = details;

            if (activeFilter?.length === 0 || !grabing || _resourceType !== 'xhr') return;

            if (activeFilter?.some(item => method === item.method)) {
                details.getContent(content => console.log('content=', content));
            }
        } catch (e) {
            console.log('糟糕,出错了!!!');
        }
    }, []);

    useEffect(() => {
        if (handleListenerRef.current) {
            chrome.devtools.network.onRequestFinished.removeListener(handleListenerRef.current);
        }
        if (activeFilter?.length === 0 || !grabing) return;
        const listener = (datails: RequestFinished) => handleListener(datails, grabing, activeFilter);
        handleListenerRef.current = listener;
        chrome.devtools.network.onRequestFinished.addListener(listener);
    }, [activeFilter, grabing, handleListener]);

    return (
        <h1>demo</h1>
    );
};

总结:

问题:

  1. addListener 执行时回调函数 handleListener 是什么就是什么,即便后来 handleListener 变了监听事件触发时也是使用的定义时传入的
  2. removeListener 不是一个直接执行的函数,执行完就取消监听了,而是需要一个参数,且参数需要和当时 addListener 使用的一样,必须是同一个变量
    方案:
  3. 每次回调函数变化时重新进行监听
  4. 将监听函数存起来,用于 removeListener 的参数

友情链接

onRequestFinished 官方使用说明

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值