一个小时,带你玩转前端交互,零基础入门做登录界面

释放双眼,带上耳机,听听看~!

一、封装ajax

封装最严谨的ajax,可直接复制引用

ajax.js

function sendAjax(obj){
    / 先判断url是否传入
    if(!obj.url){
        / 没有传
        throw new Error('地址必填') / 抛出自定义错误
    }
    / 传入了之后需要验证url是否是字符串
    if(Object.prototype.toString.call(obj.url) !== '[object String]'){
        throw new Error('地址必须是字符串')
    }
    / 判断请求方式是否传入
    if(!obj.method){
        obj.method = 'get'
    }
    / 传入了 - 验证是否是get或post
    if(obj.method.toLowerCase()!=='get' && obj.method.toLowerCase()!=='post'){
        throw new Error('请求方式必须是get或post')
    }
    / 判断async是否传入
    if(obj.async === undefined){
        obj.async = true
    }
    / 判断类型
    if(Object.prototype.toString.call(obj.async) !== '[object Boolean]'){
        throw new Error('async必须是布尔值')
    }
    / 判断是否传入success
    if(!obj.success){
        obj.success = function(){}
    }
    / 判断是否是函数
    if(Object.prototype.toString.call(obj.success) !== '[object Function]'){
        throw new Error('success必须是函数')
    }   
    if(!obj.error){
        obj.error = function(){}
    }
    if(Object.prototype.toString.call(obj.error) !== '[object Function]'){
        throw new Error('error必须是函数')
    }
    / 判断数据是否传入
    var str = '';
    if(obj.data){
        / 判断类型
        if(Object.prototype.toString.call(obj.data) === '[object String]'){
            str = obj.data
        }else if(Object.prototype.toString.call(obj.data) === '[object Object]'){
            / 对象要处理成字符串
            var f = '';
            for(var attr in obj.data){
                str += f + attr + '=' + obj.data[attr]
                f = '&'
            }
        }else{
            throw new Error('非法数据')
        }
        / 如果是get请求,需要将数据拼接在地址后
        if(obj.method.toLowerCase() === 'get'){
            obj.url += '?' + str
        }
    }
    / 判断希望请求回来的数据格式
    if(!obj.dataType){
        obj.dataType = 'json'
    }
    / 如果传了
    if(obj.dataType.toLowerCase()!=='json' && obj.dataType.toLowerCase()!=='text' && obj.dataType.toLowerCase()!=='xml'){
        throw new Error('dataType非法')
    }
    /*
    {
        url:'',
        method:'',
        data:'',
        async:'',
        success:function(){},
        error:'',
        dataType:'text/json/xml'
    }
    */
    var xhr = new XMLHttpRequest;
    xhr.onreadystatechange = function(){
        if(xhr.readyState === 4){
            if(parseInt(xhr.status/100) === 2){
                / 确定要不要转对象
                switch(obj.dataType.toLowerCase()){
                    case 'json':
                        var res = xhr.responseText;
                        res = JSON.parse(res)
                    break;
                    case 'xml':
                        var res = xhr.responseXML;
                    break;
                    case 'text':
                        var res = xhr.responseText;
                    break;  
                }   
                obj.success(res)
            }else{
                obj.error()
            }
        }
    }
    xhr.open(obj.method,obj.url,obj.async)
    if(obj.method.toLowerCase() === 'post' && obj.data){
        / 设置请求头
        xhr.setRequestHeader('content-type','application/x-www-form-urlencoded')
        xhr.send(str)
        return
    }
    xhr.send()
}



function promiseAjax(obj){
    return new Promise(function(resolve,reject){
        / 先判断url是否传入
        if(!obj.url){
            // 没有传
            throw new Error('地址必填') /抛出自定义错误
        }
        /传入了之后需要验证url是否是字符串
        if(Object.prototype.toString.call(obj.url) !== '[object String]'){
            throw new Error('地址必须是字符串')
        }
        / 判断请求方式是否传入
        if(!obj.method){
            obj.method = 'get'
        }
        / 传入了 - 验证是否是get或post
        if(obj.method.toLowerCase()!=='get' && obj.method.toLowerCase()!=='post'){
            throw new Error('请求方式必须是get或post')
        }
        / 判断async是否传入
        if(obj.async === undefined){
            obj.async = true
        }
        / 判断类型
        if(Object.prototype.toString.call(obj.async) !== '[object Boolean]'){
            throw new Error('async必须是布尔值')
        }

        / 判断数据是否传入
        var str = '';
        if(obj.data){
            / 判断类型
            if(Object.prototype.toString.call(obj.data) === '[object String]'){
                str = obj.data
            }else if(Object.prototype.toString.call(obj.data) === '[object Object]'){
                / 对象要处理成字符串
                var f = '';
                for(var attr in obj.data){
                    str += f + attr + '=' + obj.data[attr]
                    f = '&'
                }
            }else{
                throw new Error('非法数据')
            }
            / 如果是get请求,需要将数据拼接在地址后
            if(obj.method.toLowerCase() === 'get'){
                obj.url += '?' + str
            }
        }
        / 判断希望请求回来的数据格式
        if(!obj.dataType){
            obj.dataType = 'json'
        }
        / 如果传了
        if(obj.dataType.toLowerCase()!=='json' && obj.dataType.toLowerCase()!=='text' && obj.dataType.toLowerCase()!=='xml'){
            throw new Error('dataType非法')
        }
        /*
        {
            url:'',
            method:'',
            data:'',
            async:'',
            success:function(){},
            error:'',
            dataType:'text/json/xml'
        }
        */
        var xhr = new XMLHttpRequest;
        xhr.onreadystatechange = function(){
            if(xhr.readyState === 4){
                if(parseInt(xhr.status/100) === 2){
                    / 确定要不要转对象
                    switch(obj.dataType.toLowerCase()){
                        case 'json':
                            var res = xhr.responseText;
                            res = JSON.parse(res)
                        break;
                        case 'xml':
                            var res = xhr.responseXML;
                        break;
                        case 'text':
                            var res = xhr.responseText;
                        break;  
                    }   
                    resolve(res)
                }else{
                    reject()
                }
            }
        }
        xhr.open(obj.method,obj.url,obj.async)
        if(obj.method.toLowerCase() === 'post' && obj.data){
            / 设置请求头
            xhr.setRequestHeader('content-type','application/x-www-form-urlencoded')
            xhr.send(str)
            return
        }
        xhr.send()
    })
    
}

二、回调地狱的终极解决方案

在这里插入图片描述

ASYNC/AWAIT

es7提供了async/await来编写异步代码,是回调地狱的终极解决方案。

他可以将异步代码写的和同步代码一样。

语法:

async function fn() {
	const res = await promise对象
}

只要是一个 promise 对象,那么我们就可以使用 async/await 来书写

例:通过宝安区找到广东省

思考:

根据 宝安区 这个名字,找到所属的省份名称
根据这个名称找到市的id - 宝安区的pid
根据这个pid找到对应的市 - 市的pid - 省的id
根据这个id查询到省份

async function fn(){
    // await必须在async修饰的函数内部使用
    // await用来修饰一个promise对象
    var res = await promiseAjax({ // await可以等待promise中异步操作有了结果
        url:"area.php",
        data:{
            name:"宝安区"
        }
    })

    // console.log(res);
    var {pid} = res;
    var city = await promiseAjax({
        url:"city.php",
        data:{
            id:pid
        }
    })

    console.log(city);
    var {pid} = city;

    var province = await promiseAjax({
        url:"province.php",
        data:{
            id:pid
        }
    })

    console.log(province);
}
fn()

使用说明:

  1. async修饰的函数,需要调用的话,就正常调用
  2. await必须包在async修饰的函数中

查询省份.html:



<script src="./login/js/ajax.js"></script>
<script>
、

    // console.log(res);
    var {pid} = res;
    var city = await promiseAjax({
        url:"city.php",
        data:{
            id:pid
        }
    })

    console.log(city);
    var {pid} = city;

    var province = await promiseAjax({
        url:"province.php",
        data:{
            id:pid
        }
    })

    console.log(province);
}
fn()
</script>

area.php

<?php
header("content-type:text/html;charset=utf8");
$name = $_GET['name'];
$con = mysqli_connect('localhost','root','root','gp6');
mysqli_query($con,'set names utf8');
$res = mysqli_query($con,"select * from address where name='$name'");
$row = mysqli_fetch_assoc($res);
echo json_encode($row);

city.php

<?php
header("content-type:text/html;charset=utf8");
$id = $_GET['id'];
$con = mysqli_connect('localhost','root','root','gp6');
mysqli_query($con,'set names utf8');
$res = mysqli_query($con,"select * from address where id=$id");
$row = mysqli_fetch_assoc($res);
echo json_encode($row);

province.php

<?php
header("content-type:text/html;charset=utf8");
$id = $_GET['id'];
$con = mysqli_connect('localhost','root','root','gp6');
mysqli_query($con,'set names utf8');
$res = mysqli_query($con,"select * from address where id=$id");
$row = mysqli_fetch_assoc($res);
echo json_encode($row);

三、总结

es6提供的promise解决回调地狱的时候,将嵌套结构做成了链式结构,所有代码都是一个完整的整体
回调地狱的终极解决方案 - es7提供了语法:async/await
async和await是关键字,async异步的,await等待 - 等待异步执行
可以等待异步代码执行结束后继续往后执行 - 将异步代码变的跟同步代码一样了

async修饰函数的
await必须在async修饰的函数内部使用
await用来修饰一个promise对象
await可以等待promise中异步操作有了结果

为TA充电
共{{data.count}}人
人已赞赏
前端

Canvas2D实现对图片进行网格变换

2021-5-27 16:41:10

前端大数据

如何让10万条数据的小程序列表如丝般顺滑

2021-5-28 12:16:17

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索