关于javascript:ajax-终结篇jsonp防抖节流

47次阅读

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

明天是咱们最初一天 ajax 的学习,这次学完总能够去 vue 了吧,我不信还有什么拦路石,先不说其余的先看看明天的内容。

1.

首先是同源策略,什么叫做同源?

如果两个页面的协定、域名、端口都雷同的话,咱们将这两个页面为同源。

那么什么同源策略呢?

是浏览器提供的一个平安性能,如果说两个页面不同源,那么 A 网站就无奈读取 B 网站的 cookie、localstorage、indexdb 等;无奈接触 B 网站的 DOM;无奈向 B 网站发送 ajax 申请

理解了同源与他相同的就是跨域,也就是下面说的协定。域名、端口只有有一个不满足那么他们就是跨域。

浏览器对跨域申请的拦挡,咱们是可能失常发动对服务器的申请的,服务器也可能感应到申请并将数据返回回来,然而就在邻近城门的时候,在浏览器门口就被一个同源策略的门卫拦挡住了,毕生之敌。

那么既然如此如何来实现跨域的申请呢?有两个形式 CORS 和 JSONP。

cors 是 w3c 规范反对 get 和 post

JSONP

原理:因为浏览器同源策略的限度,网页无奈通过 ajax 申请非同源,然而 script 这个标签是不受限制的,所以能够通过 src 这个属性申请到非同源的 script

实现::本人定义一个回调函数,而后通过另一个 script 标签的 src 属性来调用服务器和一些参数在这个参数外面 callback= 这个函数的名字就是你本人回调函数的名字而后前面跟上你本人的参数

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>

        function fn(data) {console.log('调用胜利');
            console.log(data);
        }
        
    </script>
    <script src="http://www.liulongbin.top:3006/api/jsonp?callback=fn&name= 张三 &age=29&sex= 男"></script>


</body>
</html>

JSONP 的毛病就是他只反对 get 申请

2.

jQuery 中的 JSONP,具体的格局如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <button> 点击查看 jsonp</button>
    <script src="../day01/lib/jquery.js"></script>
    <script>
        $('button').on('click', () => {
            $.ajax({
            url : 'http://www.liulongbin.top:3006/api/jsonp?name= 张三 &age=29&sex= 男',
            dataType : 'jsonp',
            jsonpCallback : 'fn',
            success : res => console.log(res)
        })
        })
    </script>
</body>
</html>

在这外面 datatype 必须制订,而后 url 中没有了 callback,因为他会本人随机生成一个 callback,你也能够本人批改,jsonpCallback 是批改回调函数名字的,jsonp 是批改 callback 的。

在 jq 中 jsonp 的一个运行过程也要晓得一下,他其实也是依附 script 标签来实现的,在申请的时候他会动静生成一个 script 标签在 header,而后申请实现又会移出这个标签。

3.

这些都学完了就能够看到一个案例,模拟淘宝的搜寻关键字案例

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
    <!-- 导入页面的根本款式 -->
    <link rel="stylesheet" href="./css/search.css" />
    <!-- 导入 jQuery -->
    <script src="./lib/jquery.js"></script>
    <!-- 3.1 插入 template 筹备用到模板引擎 -->
    <script src="./lib/template-web.js"></script>
    <!-- 3.2 定义 ui 构造 -->
    <script type="text/html" id="suggestList">
      {{each result}}
        <div class="suggest-item">{{$value[0]}}</div>
      {{/each}}
    </script>
    <style>
      .suggest-list {
        display: none;
        border: 1px solid #ccc;
      }
      .suggest-item {
        padding-left: 5px;
        line-height: 30px;
      }
      .suggest-item:hover {
        cursor: pointer;
        background-color: #eee;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <!-- Logo -->
      <img src="./images/taobao_logo.png" alt=""class="logo" />

      <div class="box">
        <!-- tab 栏 -->
        <div class="tabs">
          <div class="tab-active"> 宝贝 </div>
          <div> 店铺 </div>
        </div>
        <!-- 搜寻区域(搜寻框和搜寻按钮)-->
        <div class="search-box">
          <input type="text" class="ipt" placeholder="请输出要搜寻的内容" /><button class="btnSearch">
            搜寻
          </button>
        </div>
        <!-- 3. 在搜寻框上面增加一个盒子拿来装关键字列表 -->
        <div class="suggest-list">

        </div>
      </div>
    </div>
    <script src="./lib/jquery.js"></script>
    <script src="./lib/index.js"></script>
  </body>
</html>

通过 jsonp 和后面说到的模板引擎来实现

$(function() {
    // 1. 先获取输入框的文字
    $('.ipt').on('keyup', function(e) {let iptText = $(this).val().trim()
        if (iptText == '') {
            // 4. 搜寻关键词为空时须要暗藏搜寻列表
            return $('.suggest-list').empty().hide()
        } else {
            // 2.1 调用获取关键字函数
        getSearchList(iptText)
        }
    })
    // 2. 封装获取倡议列表的函数
    function getSearchList(text) {
        $.ajax({
            url : 'http://suggest.taobao.com/sug?q='+text+'',
            dataType : 'jsonp',
            success : res => {getHtml(res)
            }
        })
    }
    // 3.3 调用函数并渲染
    function getHtml(res) {if (res.result.length <= 0) {return $('.suggest-list').empty().hide()
        } else {let htmlStr = template('suggestList', res)
            console.log(htmlStr);
            $('.suggest-list').html(htmlStr).show()}
    }
})

4.

防抖

防抖策略就是当一个事件被触发后,提早几秒在执行回调函数,如果在这几秒内又被触发了,那么就会从新计时

次要利用场景在用户输出时间断输出一串字符,能够通过防抖策略只有在输出结束过后再去执行查问的申请这样能够无效缩小申请次数。

具体怎么来实现须要一个定时器,而后定义防抖函数,这个函数外面开启定时器获取 jsonp 数据渲染 html 都在这外面调用,在用户键盘事件这里革除定时器,输出一个革除一个输出一个革除一个,所以只有输出的够快,就达不到进入执行这个定时器的门槛,当你停下输出失常执行代码,就会开始执行定时器,去调用去申请去渲染

$(function() {
    // 防抖 1 定义一个延时器
    var timer = null
    // 防抖 2 定义防抖函数
    function debounceSearch(text) {timer = setTimeout(() => {getSearchList(text)
        }, 500);
    }
    // 1. 先获取输入框的文字
    $('.ipt').on('keyup', function(e) {
        // 防抖 3 一进来先革除定时器,按一下清一下
        clearTimeout(timer)
        let iptText = $(this).val().trim()
        if (iptText == '') {
            // 4. 搜寻关键词为空时须要暗藏搜寻列表
            return $('.suggest-list').empty().hide()
        } else {
            // 2.1 调用获取关键字函数
        // getSearchList(iptText)
        // 防抖 4 调用获取关键字函数由定时器执行相当于等你输完了在执行
        debounceSearch(iptText)
        }
    })
    // 2. 封装获取倡议列表的函数
    function getSearchList(text) {
        $.ajax({
            url : 'http://suggest.taobao.com/sug?q='+text+'',
            dataType : 'jsonp',
            success : res => {getHtml(res)
            }
        })
    }
    // 3.3 调用函数并渲染
    function getHtml(res) {if (res.result.length <= 0) {return $('.suggest-list').empty().hide()
        } else {let htmlStr = template('suggestList', res)
            console.log(htmlStr);
            $('.suggest-list').html(htmlStr).show()}
    }
})

缓存搜寻

就是当咱们输出一个数据的时候又增加一个关键字,而后删了有输出第一个关键字这个时候申请了三次,其中第一次和第三次是反复的,怎么解决

先定义一个全局的缓存对象,将搜寻后果缓存到缓存对象中,优先从缓存中获取数据.

$(function() {
    // 防抖 1 定义一个延时器
    var timer = null
    // 防抖 2 定义防抖函数
    function debounceSearch(text) {timer = setTimeout(() => {getSearchList(text)
        }, 500);
    }
    // 缓存 1 定义一个全局空对象
    var resObj = {}
    // 1. 先获取输入框的文字
    $('.ipt').on('keyup', function(e) {
        // 防抖 3 一进来先革除定时器,按一下清一下
        clearTimeout(timer)
        let iptText = $(this).val().trim()
        if (iptText == '') {
            // 4. 搜寻关键词为空时须要暗藏搜寻列表
            return $('.suggest-list').empty().hide()
        } else {
            // 缓存 3 当咱们输出值得时候就去判断一下有没有对象里有没有该值如果有那间接渲染就是不必再去申请数据
            if (resObj[iptText]) {getHtml(resObj[iptText])
            } else {
                // 2.1 调用获取关键字函数
        // getSearchList(iptText)
        // 防抖 4 调用获取关键字函数由定时器执行相当于等你输完了在执行
        debounceSearch(iptText)
            }
            
        }
    })
    // 2. 封装获取倡议列表的函数
    function getSearchList(text) {
        $.ajax({
            url : 'http://suggest.taobao.com/sug?q='+text+'',
            dataType : 'jsonp',
            success : res => {console.log(res);
                getHtml(res)
            }
        })
    }
    // 3.3 调用函数并渲染
    function getHtml(res) {if (res.result.length <= 0) {return $('.suggest-list').empty().hide()
        } else {let htmlStr = template('suggestList', res)
            // console.log(htmlStr);
            $('.suggest-list').html(htmlStr).show()
            // 缓存 2 所有获取数据输出结束在这里获取输出的最终值保留进对象里
            resObj[$('.ipt').val().trim()] = res
        }
    }
})

5.

节流

节流策略就是能够缩小一段时间事件的触发频率,通过一个节流阀达到本不须要这么高的触发率,让资源空进去

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        html,body {
            margin: 0;
            padding: 0;
        }
        img {position: absolute;}
    </style>
</head>
<body>
    <img src="./angel.gif" alt="">
    
    <script>
        /* 一般版
        var img = document.querySelector('img')
        document.onmousemove = function(e) {// console.log(11);
            img.style.left = e.pageX + 'px'
            img.style.top = e.pageY + 'px'
        } */
        // 节流版
        var img = document.querySelector('img')
        var timer = null
        document.onmousemove = function(e) {// console.log(11);
            if (timer) {return} else {timer = setTimeout(function() {
                    img.style.left = e.pageX + 'px'
                    img.style.top = e.pageY + 'px'
                    timer = null
                },16)
            }
            console.log(11);
        }
    </script>
</body>
</html>

正文完
 0