• 解决一则诡异的javascript函数不执行的问题


    有个vue 音乐播放器项目,由于之前腾讯的搜索接口没法用了,于是改成了别家的搜索接口。

    但是由于返回数据结构不一样,代码重构的工作量还是挺大的:包括数据请求,数据处理,dom渲染,处理逻辑都进行了大规模的修改。最后改的差不多了。

    还有最后一个功能:搜索推荐,当鼠标滚动时,会不断加载更多记录,也就是searchMore(实际上就是分页加载), 直到全部记录加载完成为止,此时就不能再滚动了。如下图:

     那么这里需要一个逻辑:判断searchMore搜索更多的时候是否已经加载到最后一条记录了

    这里使用的是一个checkMore函数:

    1. // 判断全部歌曲是否已经加载完毕
    2. checkMore(data) {
    3. console.log("checkmore收到数据==》",data)
    4. if (
    5. // result是当前已经加载数据的列表, data.songCount是该搜索关键字的总记录数
    6. this.result.length >= data.songCount
    7. ) {
    8. // 使用hasMore作为列表数据是否全部加载完毕的标识
    9. this.hasMore = false;
    10. }
    11. },

    这里使用hasMore作为列表数据是否全部加载完毕的全局标识。

    而checkMore函数是嵌入到searchMore函数的, 通过控制hasMore的标识来决定是否发起request请求。

    1. searchMore() {
    2. console.log("searchMore 执行了。。。。。")
    3. if (!this.hasMore) {
    4. return;
    5. }
    6. this.page++;
    7. const data = {
    8. query: this.query,
    9. limit: this.perpage,
    10. offset: (this.page - 1) * this.perpage,
    11. };
    12. search(data.query,data.limit,data.offset).then((res) => {
    13. if ( res.code === HTTP_OK && res.result.songs.length > 0 ) {
    14. this._normalizeSongs(res.result.songs).then((resp) => {
    15. this.result = this.result.concat(resp);
    16. });
    17. }
    18. this.checkMore(res.result);
    19. });
    20. },

    但是这里非常奇怪的是,checkMore似乎失效了,因为无论滚动多少次,都会一直发起http请求。

    很明显这不是我的预期,到底是哪里出现了问题呢?

    我仔细检查了checkMore的逻辑,并没有发现任何问题。

    然后也做了断点调试,也没有发现任何线索。

    于是终于祭起了终极console.log大法!终于发现了关键的线索:

    checkMore函数总共只执行了2次,searchMore执行了3次

    而按照代码逻辑:首次search的时候checkMore会执行一次,然后以后每次searchMore都会执行checkMore函数

    也就是说: 实际情况是:从第二次滚动(searchMore)开始:checkMore就没再执行了!

     那么是什么原因导致了checkMore没有执行呢?

    再看看console的报错信息:

     看到这里终于恍然大悟了:肯定是这里抛出了异常,导致了后面的代码没有执行!

    那么res.result.songs.length为什么会抛undined异常呢,看看response就知道了:

     原来: 从第二次searchMore开始,result底下就已经没有songs属性了!

    那么res.result.songs就必然是一个undefined了!

    所以解决办法有两个:

    1. 把checkMore函数放到searchMore函数的第一行(不推荐):

            这样就规避了后面函数的异常所产生的中断执行的影响。但是这种方法不推荐,因为它没有从根本上解决抛异常引发中断执行的问题

    2. 使用object的hasOwnProperty方法去判断对象上是否有某属性,这样就能规避异常的问题

    // 判断对象是否有某属性

    object.hasOwnProperty("属性名称")

    1. searchMore() {
    2. console.log("searchMore 执行了。。。。。")
    3. if (!this.hasMore) {
    4. return;
    5. }
    6. this.page++;
    7. const data = {
    8. query: this.query,
    9. limit: this.perpage,
    10. offset: (this.page - 1) * this.perpage,
    11. };
    12. search(data.query,data.limit,data.offset).then((res) => {
    13. // 注意:如果这里发生了异常,那么后面的this.checkMore是不会执行的,这个是关键!
    14. // 所以这里使用hasOwnProperty方法来判断对象是否有某属性,从而不会触发异常
    15. if (res.code === HTTP_OK && res.result.hasOwnProperty('songs')) {
    16. this._normalizeSongs(res.result.songs).then((resp) => {
    17. this.result = this.result.concat(resp);
    18. });
    19. }
    20. this.checkMore(res.result);
    21. });
    22. },

    问题解决:

    总结:

    .不要小看对象取属性带来的undefined异常问题,因为这种异常往往非常隐蔽!很难觉察到它所带来的诡异后果. 如有可能尽量使用hasOwnProperty方法判断属性是否存在!

    2.  在 JavaScript 中,如果前面的代码抛出了异常但没有提前捕获,程序将在抛出异常的地方终止执行,则后面的代码将不会执行。如果你使用了try/catch块来捕获异常,并且在catch 块中处理了异常,那么后面的代码才会执行。这就是 JavaScript 中的异常处理机制。

  • 相关阅读:
    Layui + Flask | 表单元素(组件篇)(06)
    C++中volatile使用注释(①不被编译器优化,②多线程安全,③修饰指针或变量注意事项)
    数据结构的无头单向链表
    JY-7GA/1电压继电器
    C++动态内存分配
    C++ Reference: Standard C++ Library reference: C Library: ctime: clock
    PyTorch 2.0 重磅发布:一行代码提速 30%
    分布式事务最终一致性的简单案例
    基于python的疫情数据可视化分析系统设计与实现-计算机毕业设计源码+LW文档
    MySql(44)事务的基本认识
  • 原文地址:https://blog.csdn.net/jiaohuizhuang6019/article/details/133931395