promise将回调函数取代,解决回调地狱

ajax回调函数版本

// 防抖
function antishake(func, wait) {
    let timer = null
    return function () {
        clearTimeout(timer)
        timer = setTimeout(() => {
            func()
        }, wait)
    }
}
// 节流
function throttle(func,wait){
    // let timer = null//节流阀
    let flag = false
    return function(){
        
        if(flag) return// null====>false 如果是null(false)就执行下面代码(下面代码执行timer就变为true了),不是null就返回直接跳过     车上没人就上车 车上有人就直接跳过
        flag = true
        let timer = setTimeout(()=>{//上车了 车上有人
            func() // 到站了
            // timer = null // 下车
            flag = false
        },wait)

    }
}
//兼容各大浏览器
function createXhr(){
    if(window.XMLHttpRequest){
        return new XMLHttpRequest()
    }
    return new ActiveXObject("Microsoft.XMLHTTP");//兼容ie6
}
function ajax(options){//option是一个对象
    // 先准备默认的对象 存储默认值
    let defaultObj = {
        method:"GET",//默认为get请求
        url: "",
        aync:true,
        data:"",
        dataType: 'json',
        callback(){}
    }
    // url地址没有传递或者传递的是空 直接返回出去
    if(!options.url || options.url==""){
        throw new Error('url地址必须不为空')
    }
    // 取出options里面的数据 给到defaultObj 给后面使用
    for(let key in options){
        defaultObj[key] = options[key]//将对应的key进行赋值
    }
    // 判断(验证)method
    // defaultObj.method.toUpperCase()全字母转大写
    // defaultObj.method.toLocaleUpperCase()首行转大写
    if(defaultObj.method.toUpperCase() != "GET" && defaultObj.method.toUpperCase() != "POST"){
        throw new Error("请求方式错误")
    }
    // 判断callback是否为函数
    if(!typeof defaultObj.callback == "function"){
        throw new Error("回调函数类型错误")
    }
    // 判断aync是否为boolean类型
    if(!typeof defaultObj.aync == "boolean"){
        throw new Error("aync必须是boolean类型")
    }
    // 如果是get请求 就对对应的数据和请求地址拼接
    if(defaultObj.method.toUpperCase() == "GET"){
        defaultObj.url+='?'+defaultObj.data
    }
    if(defaultObj.data.toString() == "[object Object]"){
        let dataStr = ""
        for(let key in defaultObj.data){
            dataStr+=key+'='+defaultObj.data[key]+'&'
        }
        // 删除最后一个符号
        dataStr = dataStr.slice(0,-1)
        defaultObj.data = dataStr
    }
    // 创建一个请求对象
    let xhr = createXhr()
    // 设置open请求
    xhr.open(defaultObj.method.toUpperCase(),defaultObj.url,defaultObj.aync)
    // send发送请求
    if(defaultObj.method.toUpperCase()=="POST"){
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
        xhr.send(defaultObj.data)
    }else{
        xhr.send()
    }
    // 4、监听
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4 && /^20\d$/.test(xhr.status)) {
            //5.接收响应
            if(defaultObj.dataType == "json"){
                let res = JSON.parse(xhr.responseText)//转化为json对象
                defaultObj.callback(res)//回调,将对应响应结果带出
            }else{
                defaultObj.callback(xhr.responseText)//调用回调方法 将对应响应结果带出
            }      
        }
    }
}

jsonp回调函数版本

function jsonp(object){
    // {链接地址,参数(对象),回调函数名字,回调函数}
    let {url,params,callbackName,callback} = object
    // 给window添加方法
    // 随机生成一个函数名 不能重复
    let fnName = "fn" + Date.now() + Math.ceil(Math.random()*10000)
    // 将对应回调函数添加給window 添加的函数名随机
    window[fnName] = callback
    // 创建标签script
    let script = document.createElement("script")
    // 将方法名拼接到url地址后面 跨域执行xxx
    url += `?${callbackName}=${fnName}`
    // 将参数拼接
    url += joinParams(params)
    // 将这个url地址给到script标签的src属性(自带的属性)
    script.src = url
    // 将script加到body
    document.body.appendChild(script)
    // 判断是否已经加载成功,加载成功后就删除script节约空间
    script.onload = function(){
        script.remove()
        delete window[fnName]
    }
}
function joinParams(params){
    let str = ''
    // 取出对象的值
    for(let key in params){
        str+=`&${key}=${params[key]}`
    }
    return str
}

ajax promise版本(无回调函数)

// 防抖
function antishake(func, wait) {
    let timer = null
    return function () {
        clearTimeout(timer)
        timer = setTimeout(() => {
            func()
        }, wait)
    }
}
// 节流
function throttle(func,wait){
    // let timer = null//节流阀
    let flag = false
    return function(){
        
        if(flag) return// null====>false 如果是null(false)就执行下面代码(下面代码执行timer就变为true了),不是null就返回直接跳过     车上没人就上车 车上有人就直接跳过
        flag = true
        let timer = setTimeout(()=>{//上车了 车上有人
            func() // 到站了
            // timer = null // 下车
            flag = false
        },wait)

    }
}
//兼容各大浏览器
function createXhr(){
    if(window.XMLHttpRequest){
        return new XMLHttpRequest()
    }
    return new ActiveXObject("Microsoft.XMLHTTP");//兼容ie6
}
function ajax(options){//option是一个对象
    // 先准备默认的对象 存储默认值
    let defaultObj = {
        method:"GET",//默认为get请求
        url: "",
        aync:true,
        data:"",
        dataType: 'json',
    }
    // url地址没有传递或者传递的是空 直接返回出去
    if(!options.url || options.url==""){
        throw new Error('url地址必须不为空')
    }
    // 取出options里面的数据 给到defaultObj 给后面使用
    for(let key in options){
        defaultObj[key] = options[key]//将对应的key进行赋值
    }
    // 判断(验证)method
    // defaultObj.method.toUpperCase()全字母转大写
    // defaultObj.method.toLocaleUpperCase()首行转大写
    if(defaultObj.method.toUpperCase() != "GET" && defaultObj.method.toUpperCase() != "POST"){
        throw new Error("请求方式错误")
    }
    // 判断callback是否为函数
    if(!typeof defaultObj.callback == "function"){
        throw new Error("回调函数类型错误")
    }
    // 判断aync是否为boolean类型
    if(!typeof defaultObj.aync == "boolean"){
        throw new Error("aync必须是boolean类型")
    }
    // 如果是get请求 就对对应的数据和请求地址拼接
    if(defaultObj.method.toUpperCase() == "GET"){
        defaultObj.url+='?'+defaultObj.data
    }
    if(defaultObj.data.toString() == "[object Object]"){
        let dataStr = ""
        for(let key in defaultObj.data){
            dataStr+=key+'='+defaultObj.data[key]+'&'
        }
        // 删除最后一个符号
        dataStr = dataStr.slice(0,-1)
        defaultObj.data = dataStr
    }
    // 创建一个请求对象
    let xhr = createXhr()
    // 设置open请求
    xhr.open(defaultObj.method.toUpperCase(),defaultObj.url,defaultObj.aync)
    // send发送请求
    if(defaultObj.method.toUpperCase()=="POST"){
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
        xhr.send(defaultObj.data)
    }else{
        xhr.send()
    }
    // 4、监听
    return new Promise(()=>{
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4 && /^20\d$/.test(xhr.status)) {
                //5.接收响应
                let res
                if(defaultObj.dataType == "json"){
                    res = JSON.parse(xhr.responseText)//转化为json对象
                }else{
                    res = xhr.status
                }  
                success(res)    
            }
            //服务器的响应 状态码
            if(!/^20\d$/.test(xhr.status)){
                error(xhr.status)
            }
        }
    })
    
}

jsonp promise版本(无回调函数)

function jsonp(object){
    // {链接地址,参数(对象),回调函数名字,回调函数}
    let {url,params,callbackName} = object
    // 给window添加方法
    // 随机生成一个函数名 不能重复
    return new Promise((success,error)=>{
        try {
            let fnName = "fn" + Date.now() + Math.ceil(Math.random()*10000)
            // 将对应回调函数添加給window 添加的函数名随机
            window[fnName] = success
            // 创建标签script
            let script = document.createElement("script")
            // 将方法名拼接到url地址后面 跨域执行xxx
            url += `?${callbackName}=${fnName}`
            // 将参数拼接
            url += joinParams(params)
            // 将这个url地址给到script标签的src属性(自带的属性)
            script.src = url
            // 将script加到body
            document.body.appendChild(script)
            // 判断是否已经加载成功,加载成功后就删除script节约空间
            script.onload = function(){
                script.remove()
                delete window[fnName]
            }
            script.onerror = function(){
                error("错误")
            }
        } catch (error) {
            error("又错了")
        }
        
    })
    
}
function joinParams(params){
    let str = ''
    // 取出对象的值
    for(let key in params){
        str+=`&${key}=${params[key]}`
    }
    return str
}

测试 

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <input type="text" placeholder="停止输入1s后搜索">
    <!-- <script src="./JSONP.js"></script> -->
    <script src="./promiseJSONP.js"></script>
    <script src="./myajax.js"></script>
    <script>
        let url = "https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su"
        let input = document.querySelector('input')

        // promiseJSONP.js用return Premise
        let antishake1 = antishake(function () {
            let inputValue = input.value
            let promise1 = jsonp({
                url,
                params: {
                    wd: inputValue
                },
                callbackName: 'cb',
            })
            promise1.then((res) => {
                console.log(res)
            })
            promise1.catch((err) => {
                console.log(err);
            })
        }, 1000)
        input.oninput = function () {
            antishake1()
        }
        // JSONP.js用callback
        // jsonp({
        //     url,
        //     params:{
        //         wd:"江月奥"
        //     },
        //     callbackName:'cb',
        //     callback(res){
        //         console.log(res)
        //     }
        // })


        let promise1 = jsonp({
            url,
            params: {
                wd: "江月奥"
            },
            callbackName: 'cb',
        })
        promise1.then((res) => {
            console.log(res)
        })
        promise1.catch((err) => {
            console.log(err);
        })
    </script>
</body>

</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值