js 防抖节流,同步异步,promise

防抖

   防抖  指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
  //非立即执行
        let box = document.getElementById('box')
        let num = 1;
        function add() {
            box.innerHTML = num++
        }
        function debounce(fn,time) {
            //这个作用域不销毁
            //保护保存
             let timer = null;
             return function(){
                 clearTimeout(timer)
                 timer = setTimeout(()=>{
                     fn.call(this)
                 },time)
             }
         }
         box.onmousemove = debounce(add,1000)
        // onmousemove绑定的真正的函数是debounce返回值


        //立即执行:如果n秒内不再触发事件,函数才会执行;
        //防止恶意触发频繁点击,n秒触发一次
         function debounce(fn,time) {
             let timer = null;
             return function() {
                 clearTimeout(timer);
                 let now = !timer
                 timer = setTimeout(()=>{
                     timer = null;
                 },time)
                 if(now){
                     fn.call(this)
                 }
             }
         }
         box.onmousemove = debounce(add,1000)



        //合并版
        function debounce(fn, time, immediate) {
            let timer
            return function () {
                if (immediate) {
                    clearTimeout(timer);
                    let now = !timer;
                    timer = setTimeout(() => {
                        timer = null;
                    }, time)
                    if (now) {
                        fn.call(this)
                    };
                } else {
                    clearTimeout(timer);
                    timer = setTimeout(() => {
                        fn.call(this)
                    }, time);
                }
            }

        }
        box.onmousemove = debounce(add, 1000, true)



节流

 节流  指连续触发事件但是在 n 秒中只执行一次函数。节流会稀释函数的执行频率。
      // onmousemove :当鼠标在元素上滑动触发
        // onscroll:滚动条
        // onmouseover: 移入
        // onmouseout: 移出
        //时间戳版  
        function throttle(fn,time){
             let previous = 0;
             return function() {
                 let now = Date.now();
                 if(now - previous >= time){
                     fn.call(this);
                     previous = now;
                 }
             }
         }
         box.onmousemove = throttle(add,2000);
        //定时器版
         function throttle(fn, time) {
             let timer;
             return function () {
                 if (!timer) {
                     timer = setTimeout(() => {
                         timer = null
                         fn.call(this)
                     },time)
                 }
		     }
        }
        box.onmousemove = throttle(add, 2000);


        //合并版
        function throttle(fn, time, type) {
            if (type === 1) {
                var previous = 0;
            } else {
                var timer;
            }
            return function () {
                if (type === 1) {
                    let now = Date.now();
                    if (now - previous >= time) {
                        fn.call(this);
                        previous = now;
                    }
                } else if (type === 2) {
                    if (!timer) {
                        timer = setTimeout(() => {
                            timer = null;
                            fn.call(this);
                        }, time);
                    }
                }
            }
        }
        box.onmousemove = throttle(add, 2000, 1);

定时器同异步

  时间循环流程
	  执行栈   等待栈
	  调用栈中的同步任务都执行完毕,栈内被清空了,就代表主线程空闲了,这个时候就会去任务队列中按照顺序读取一个任务放入到栈中执行。每次栈内被清空,都会去读取任务队列有没有任务,有就读取执行,一直循环读取-执行的操作,就形成了事件循环。
	     当浏览器解析JS时,会先把所有同步代码执行完,然后再执行异步
	 js是单线程   js同一时间只能执行一行代码
	 浏览器是多线程
	 线程是一个小的进程
     异步  :定时器  ajax  事件(onload,onclick,promise,async,await)
	    1.如果两个定时器都在for循环的上面,谁的时间小,先执行谁,如果时间相同 按顺序执行
	    2.当同步代码执行完毕,会对异步任务进行比较,谁先到达执行时间,先执行谁
	 当js运行时,分为主任务队列和等待任务队列,主任务都是同步的,异步是等待任务队列,只有主任务队列执行完毕,才会执行等待任务队列

    js将请求数据这个任务交给了浏览器,浏览器去向服务器请求数据,服务器把数据返回给浏览器
 setInterval  每隔多长时间执行一次
      setTimeout    到了一定时间执行一次
      浏览器最小识别时间:谷歌 5-6ms  火狐 10-12  IE 13-15
      setTimeout  当代码运行到setTimeout 这里时,浏览器会给当前定时器记录一个开始时间
      //定时器的返回值是代表当前页面中第几个定时器  

      function fn(){
          var a =setTimeout(function(){},1000)
          console.log(a); //2
            
      }
      var timer = setTimeout(function(a,b){
        console.log(a,b);//1 2
        return 100

      },2000,1,2) //1和2传给了function函数
      fn();
      console.log(timer);//1

    计算for循环的时间
      var cur = Date.now();
      for(var i = 0;i<10000000;i++){

      }
      console.log(Date.now()-cur);
      

 
    setTimeout(function(){
        //这个函数是异步的
        console.log(100);       //5
    },20)
    console.log(300);          //1
    setTimeout(function(){
        //这个函数是异步的
        console.log(400);       //4
    },10)
    for(var i=0;i<1000000;i++){
        //for 同步
    }
    console.log(200);           //2
    window.onload = function(){
        setTimeout(function(){
        //这个函数是异步的
        console.log(500);           //7
    },20)
    console.log(600);             //3
    setTimeout(function(){
        //这个函数是异步的
        console.log(700);           //6
    },10)
    for(var i=0;i<1000000;i++){
        //for 同步
    }
    console.log(800);              //4
    }
    //输出 300 200 100   
    //时间一样 异步一次走  不一样 谁快谁先走

多方向运动公式

  //当点击盒子的时候,让盒子横向运动500px,纵向运动300px,width:200px;height:200px;
        function linear(t, b, c, d) {
            // t:运动过的时间
            // b:起始位置
            // c:要运动总距离
            // d:需要的总时间
            //此时此刻位置    c/d*t+b
            return c / d * t + b
        }
        let box = document.getElementById('box');
        let target = {
            left: 500,
            top: 300,
            width: 200,
            height: 200
        }
        let curStart = getComputedStyle(box)
        let begin = {
            left: parseFloat(curStart.left),
            top: parseFloat(curStart.top),
            width: parseFloat(curStart.width),
            height: parseFloat(curStart.height),
        };
        let duration = 3000;
        let change = {};
        let timer = null;
        //计算出变化的值
        for (let key in target) {
            change[key] = target[key] - begin[key]
        }
        box.onclick = function () {
            clearInterval(timer)
            let t = 0
            timer = setInterval(() => {
                t += 20;
                for (let key in change) {
                    let cur = linear(t, begin[key], change[key], duration);
                    box.style[key] = cur + 'px';
                }
                if (t >= duration) {
                    clearInterval(timer)
                    timer = setInterval(() => {
                        t -= 20;
                        for (let key in change) {
                            let cur = linear(t, begin[key], change[key], duration);
                            box.style[key] = cur + 'px';
                            if(t<=0){{
                                clearInterval(timer)
                            }}
                        }
                        
                    }, 20);
                }
            }, 20);
        }

promise

 Promise 是ES6中新增的一个类,专门用来解决异步回调地狱的问题,将异步代码同步显示出来;
     promise  三个状态 : Pending     fulfilled  rejected
    改变状态有两种可能  pending-->fulfilled  pending--> rejected
 
        $.ajax({
            url:"time/ww",
            success:function(data){
                $.ajax({
                    当第一个请求成功以后再发第二个
                    success:function(){
                        $.ajax({
                        })
                    }
                })
            }
        })
        axios  fetch 
  
        let p = new Promise(function(resolve,reject){
            //setTimeout(()=>{
                resolve();  // 调用resolve代表执then中的第一个回调,resolve代表的是成功态
                // 调用reject ,就代表执行then的的第二个回调;,失败态
                reject();
            //},1000)
        }).then(function(){
            console.log(1);
        },function(){
            console.log(2);
        }).then(function(){

        },function(){
            
        })
    //   setTimeout(function(){
    //     console.log(p);
    //   },2000)
        
        
        
        
promise的回调函数 是同步的 then对应的函数是异步的
    定时器是等待任务    又分为宏任务和微任务,当执行栈主任务队列执行完,要执行等待任务,在执行等待任务时,先执行微任务,后执行宏任务
    then  微任务    定时器  宏任务
setTimeout(function () {
                    console.log(500);
        
                }, 0)
                console.log(100);
        
                let p = new Promise(function (resolve, reject) {
                    console.log(300);
        
                    resolve();
                    console.log(200);
        
                });
                p.then(function () {
                    console.log(400);
        
                })
        
                console.log(600); */
        //100,300,200,600,400,500 
Promise.all()
	  Promise.all()  私有属性   用于多个实例 返回一个新Promise实例
     只有当p1,,p2,p3状态全部为filfulled,那么新实例才是成功的
     只要有一个rejected  就是失败
let p1 = new Promise(function(resolve,reject){
            setTimeout(function(){
                resolve(100)
            },3000)
        })
        let p2 = new Promise(function(resolve,reject){
            setTimeout(function(){
                resolve(200)
            },2000)
        })
        let p3 = new Promise(function(resolve,reject){
            setTimeout(function(){
                resolve(300)
            },4000)
        })
        let p = Promise.all([p1,p2,p3])
        p.then(function(data){
            //会将所有成功数据组装成一个新数组,传递给这个回调函数
            console.log(data);
            
        }).catch(function(data){
            //只要遇到一个失败,就将失败的值传递给这个回调
            console.log(data);
            
        })
Promise.prototype.catch()
  let p = new Promise(function(resolve,reject){
            resolve()
        })
        p.then(function(){
            console.log(1);
            throw new Error() //如果在then中抛出异常,则会执行下面catch
            //如果then中代码有异常,也会抛出错误
            //只有then链中有一个异常,就会执行最后的catch,只要在then中有失败的回调,就不再执行最后的catch了
            //catch 同步
        }).then(function(){
            console.log(5);
            
        }).catch(function(){
            console.log(2);
            
        })
        
Promise.prototype.finally()
finally方法用于指定不管 Promise 对象最后状态如何,都会执行的操作
  try{
          console.log(2);
          
      }catch(e){
        console.log(1);
        
      }finally{
          console.log(3);
          
      }
       //2   3 

    //   finally 异步
    let p = new Promise(function(resolve,reject){
            resolve()
        })
        p.then(function(){
            console.log(1);
          
        }).then(function(){
            console.log(5);
            
        }).catch(function(){
            console.log(2);

        }).finally(function(){
            console.log(1000);
            // // 这是会等到promise实例状态改变以后会触发的回调,是一个异步的;
        })
        console.log(999);
        //999 1  5  1000
Promise.race()
	Promise.race()方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。
	只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。
  let p1 = new Promise(function(resolve,reject){
            setTimeout(function(){
                resolve(100)
            },3000)
        })
        let p2 = new Promise(function(resolve,reject){
            setTimeout(function(){
                reject(200)
            },5000)
        })
        let p3 = new Promise(function(resolve,reject){
            setTimeout(function(){
                resolve(300)
            },4000)
        })
        let p = Promise.race([p1,p2,p3])
        p.then(function(data){
            console.log('成功');
            
        }).catch(function(data){
            console.log('失败');
            
        })
        
        
Promise.resolve:
	将一个对象转成一个promise的实例;返回值可以调用then方法
   Promise.resolve("foo").then(function () {

        })
        new Promise(function (resolve, reject) {
            resolve("foo")
        });

        Promise.reject("foo").then(function () {

        })
        new Promise(function (resolve, reject) {
            reject("foo")
        });
        let p = Promise.resolve();
        p.then(function () {

        })

        let a = {
            then: function () {

            }
        }

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值