【web前端】(手写js) 函数防抖|节流实现、Promise实现、Ajax实现

本文详细介绍了JavaScript中如何手动实现防抖和节流技术,同时探讨了Promise的基础原理和手动创建,以及如何从零开始构建Ajax请求。通过这些实践,提升前端开发技能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、手动实现防抖

防抖: 对于频繁触发事件,只在最后一次触发生效
// 非立即防抖:持续触发事件时,事件处理函数完全不执行,等最后一次触发结束一段时间后再执行
// 实现思路:每次触发事件时都取消之前的延时调用方法,并重设定时器
function debounce(wait, funct, ...args) {
    var timer = null
    return () => {
        clearTimeout(timer)
        timer = setTimeout(() => funct(...args), wait)
    }
}

// 立即防抖:持续触发事件时,事件处理函数会立即执行,然后不执行事件处理函数,直至最后一次
//           触发之后的一段时间后才允许再次执行事件处理函数
// 实现思路:判断是否有定时器,没有则执行事件处理函数,然后无论是否有定时器都需重设定时器
function debounce(wait, funct, ...args) {
    var timer = null
    return () => {
        if(!timer)  funct(...args)
        clearTimeout(timer)
        timer = setTimeout(() => timer = null, wait)
    }
}

window.onscroll = debounce(300, (a) => console.log(a), 1)

2、手动实现节流

节流:把频繁触发事件变为少量触发
//时间戳实现:通过时间戳记录上次事件处理执行时间,如果和现在时间差大于执行周期,则执行事件
//            处理函数并赋值执行时间为当前时间戳
function throttle(wait, funct, ...args) {
    var prev = Date.now()
    return () => {
        var now = Date.now()
        if(now - prev > wait) {
            funct(...args)
            prev = now
        }
    }
}

// 定时器实现:判断是否有定时器,没有则执行事件处理函数并重设定时器
function throttle(wait, funct, ...args) {
    var timer = null
    return () => {
        if(!timer) {
            funct(...args)
            timer = setTimeout(() => timer = null, wait)
        }
    }
}

window.onscroll = throttle(1000, (a) => console.log(a), 1)

3、手动实现Promise

class Promise {
    // 定义Promise构造函数
    constructor(excutor) {
        this.status = "pending"
        this.value = undefined
        this.reason = undefined
        // 分别存放成功、失败的回调
        this.onResolved = []    
        this.onRejected = []

        let handler = funct => {
            if(typeof(funct) === "function") {
                if(this.status === "fulfilled") funct(this.value)
                if(this.status === "rejected") funct(this.reasion)
            }
        }

        // 实现resolve回调
        let resolve = value => {
            if(this.status ===  "pending") {
                this.status = "fulfilled"
                this.value = value
                this.onResolved.forEach(handler)
            }
        }

        // 实现reject回调
        let reject = reason => {
            if(this.status ===  "pending") {
                this.status = "rejected"
                this.reason = reason
                this.onRejected.forEach(handler)
            }
        }
    
        try {
            excutor(resolve, reject)
        } catch(error) {
            reject(error)
        }
    }

    // 定义then回调
    then(resolved, rejected) {
        if(this.status === "fulfilled") {
            resolved(this.value)
        }
        if(this.status === "rejected") {
            rejected(this.reason)
        }
        if(this.status === "pending") {
            this.onResolved.push(() => {
                resolved(this.value)
            })
            this.onRejected.push() => {
                rejected(this.reason)
            })
        }
    }
}
    

// 测试promise
const promise = new Promise((resolve,reject) => {
      setTimeout(() => {
         resolve('成功')
     },1000)
}).then(
    (data) => {
        console.log('success',data);
    },
    ((err) => {
    console.log('failed',err);
    }
)

4、手动实现Ajax

浏览器的同源策略:协议、url、端口号任一不同都算为跨域请求

function ajax(url, method = "GET", data = null, async = true) {
    var XHR = XMLHttpRequest
    // 创建XMLHttpRequest对象,考虑兼容性,老版本的IE5、IE6使用ActiveX
    XHR = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXobject("Microsoft.XMLHTTP")

    XHR.open(method, url, async)
    XHR.onreadystatechange = function() {
        if(XHR.readyState == 4) {
            if(XHR.statuss >=200 && XHR.status<300) {
                alert(XHR.requestText)
            } else {
                alert("ajax服务器返回错误")
            }
        }
    }
    XHR.send(data)
}

ajax("https://www.baidu.com", "POST", "A=1&B=2")

// 利用promise封装实现Ajax
function ajax({url='',type = 'get',dataType = 'json'}){
    return new Promise((resolve,reject)=>{
        let xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXobject("Microsoft.XMLHTTP")
        xhr.open(type,url,dataType)
        xhr.onReadyStateChange = function(){
            if(xhr.readyState === 4){
                if(xhr.status >=200 && xhr.status<300){
                    resolve(xhr.response)
                }
            }else{
                reject(error)
            }
        }
        xhr.send()
    })
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值