day25-promise

回调地狱

  • 在异步的程序中想要拿到 异步程序执行的结果,必须使用回调函数
  • 当异步操作越来越多,那么回调函数嵌套就会越来越深
  • 当回调函数嵌套过多的这个请就叫做回调地狱
  • 代码的执行顺序会非常不直观,不利于维护。
  • 案例:
    • 有三个接口 data1.php data2.php data3.php
    • data2.php 需要 data1.php 中返回的数据当参数
    • data3.php 需要 data2.php 中返回的数据当参数
        <script>
            // data1请求出来的结果 当成data2的请求参数
            // data2 请求出来结果 当成 data3的请求参数
            ajax({
                url: "./data1.php",
                success: function (res) {
                    ajax({
                        url: "./data2.php",
                        data: { num: res },
                        success: function (res2) {
                            ajax({
                                url: "./data3.php",
                                data: { num: res2 },
                                success: function (res3) {
                                    console.log(res3);
                                },
                            });
                        },
                    });
                },
            });
           
        </script>

  • data1.php
<?php
    echo 10;
?>
  • data2.php
<?php
    $n1 = $_GET['num'];

    echo $n1*2;
    
?>
  • data3.php
<?php
    $num = $_GET['num'];

    echo $num+10;
?>

promise介绍

  • promise:承诺

  • promise是ES6新增的一个语法

  • 当你需要执行一个异步程序的时候,你可以把这个事情交给promise

  • promise帮你执行并且会把结果返回给你

  • promise的状态

    • pedding 执行中
    • resolved 成功状态
    • rejected 失败状态
  • promise语法

    • 创建promise对象:let p = new Promise(function(){})

    • 这个p对象有一个参数为一个函数

      • 这个函数主要的作用就是让你执行异步代码的
    • 这个p对象有两个方法:

      • p.then() 当成功的时候,会执行这个函数,这个函数中有一个参数为回调函数,主要用来接收异步执行成功返回的结果
      • p.catch() 当失败的时候,会执行这个函数,这个函数中有一个参数为回调函数,主要用来接收异步执行失败返回的结果
    • promise对象 参数为一个函数,这行函数中有两个参数:

      • resolve:是一个成功的回调函数,当执行resolve() 就相当于在执行then方法中的回调函数
      • reject:是一个失败的回调函数,当执行reject() 就相当于在执行catch方法中的回调函数
    • 注意点:只要在then中返回promise对象,那么就能继续then

promise.html

let p=new Promise(function(resolve,reject){
   ajax({
      url:"./data1.php",
      success:function(res){
         resolves(res)
      },
      error:function(err){
         reject(err);
      }
   });
});
p.then(function(res){
   let p2=new Promies((resolve,reject)=>{
       ajax({
          url:"./data2.php",
          data:{num:res},
          success:function(res2){
              resovle(res2);
          }
       })
   })
   p2.then(function(res2){
      ajax({
         url:"./data3.php",
         data:{num:res2},
         success:function(res3){
            console.log(res3);
         }
      })
   })
}).catch(function(res){
    console.log(res);
})

promise2.html

<script>
   let p=new Promise((resolve,reject)=>{
      ajax({
         url:"./data1.php",
         success:function(res1){
             resolve(res1);
         },
      });
   });
   p.then(res1=>{
      return new Promise((resolve,reject)=>{
         ajax({
             url:"./data2.php",
             data:{num:res1},
             success:function(res2){
                resolve(res2);
             },
         });
      });
   }).then(res2=>{
      return new Promies((resolve,reject)=>{
         ajax({
            url:"./data3.php",
            data:{num:res2},
            success:function(res3){
               resovle(res3);
            },
         });
      });
   }).then(data=>{
      console.log(data);
   })
</script>

promis3.html

        <script>
            let p = pAjax({
                url: "./data1.php",
                type: "post",
            });

            p.then((res) => {
                return pAjax({
                    url: "./data2.php",
                    data: { num: res },
                });
            }).then((res2) => {
                return pAjax({
                    url: "./data3.php",
                    data: { num: res2 },
                });
            }).then(data=>{
                console.log(data);
            });

封装一个promise形式的ajax请求

// 封装ajax请求
/* 
    参数:
        【1】请求的地址 
        【2】请求方式(get||post)
        【3】回调函数(用于获取异步代码执行结果),成功,失败
        【4】请求的携带的参数
        【5】设置同步或者异步
    当函数的参数 过多的时候 应该把参数 写成一个对象传递
    {
        url:'请求的地址',  //请求地址是必须
        type:'get',   选填,不填的时候 默认值为get请求 
        data:{username:'aaa',password:'123123'} || "username=aaa&password=123123",  选填,有参数就传递 没有可以不填,需要有默认值为 ''
        async:false, 选填 ,值为布尔值,不填写的时候为 true
        success:fucntion(){},  必填 请求成功之后执行的函数 获取到请求的结果
        error:function(){}  选填 请求失败之后执行的函数
    }
*/
function ajax(obj) {
    // 判断必填的属性 是否有传递
    if (!obj.url) {
        // d当url没有填写的时候 抛出错误
        throw Error("url属性不能为空");
    }

    // 判断success 是否有传递
    if (!obj.success) {
        throw Error("success属性不能为空");
    }

    // 当有一些参数没有传递的时候 需要添加默认值
    let option = {
        url: obj.url,
        type: obj.type || "get",
        data: obj.data || "",
        async: obj.async || true,
        success: obj.success,
        error: obj.error || function (err) {
            console.log(err);
        },
    };

    // 判断一下 请求方式是否正确 post || get
    if (!(option.type == "get" || option.type == "post")) {
        throw Error("type属性的取值 暂时只支持 get 和 post");
    }

    // 判断data参数 是否是 对象 或者字符串
    let datatype = Object.prototype.toString.call(option.data);
    if (!(datatype == "[object Object]" || datatype == "[object String]")) {
        throw Error("data参数的格式 暂时只支持对象或者字符串");
    }

    // 判断 async 是否是布尔值
    if (!(Object.prototype.toString.call(option.async) == "[object Boolean]")) {
        throw Error("async的取值只能为布尔值(true|| false)");
    }

    // 判断success 是否是函数
    if (
        !(Object.prototype.toString.call(option.success) == "[object Function]")
    ) {
        throw Error("success 必须是一个函数");
    }

    // 判断error参数是否为函数
    if (
        !(Object.prototype.toString.call(option.error) == "[object Function]")
    ) {
        throw Error("error 必须是一个函数");
    }

    // 如果参数为对象的时候 需要把对象转化为
    // {name:'老谢',age:48}==>name=老谢&age=18
    // "key=value&key=value"

    if (Object.prototype.toString.call(option.data) == "[object Object]") {
        let str = "";
        for (let key in option.data) {
            str += key + "=" + option.data[key] + "&";
        }
        option.data = str.substr(0, str.length - 1);
    }

    let xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function () {
        // ajax状态
        if (xhr.readyState == 4 && /^[23]\d{2}$/.test(xhr.status)) {
            // console.log(xhr.responseText);
            option.success(xhr.responseText);
        }

        // http的状态码为 4 或者 5开头的时候
        if (/^[45]\d{2}$/.test(xhr.status)) {
            option.error(xhr.responseText)
        }
    };

    // 判断请求方式
    if (option.type == "get") {
        xhr.open(option.type, `${option.url}?${option.data}`, option.async);
        xhr.send();

        return;
    }

    xhr.open(option.type, option.url, option.async);
    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    xhr.send(option.data);
}

function pAjax(obj) {
    return new Promise((resolve, reject) => {
        ajax({
            url: obj.url,
            type: obj.type,
            data: obj.data,
            async: obj.async,
            success: function (res) {
                resolve(res)
            },
            error: function(err){
                reject(err)
            }
        })
    })
}

async和await

  • async
    • 写在函数前面的一个关键字
    • 当写了async关键字之后 这个函数的返回值为promis对象
  • await
    • 等待 的必须是一个promise对象,当等到这个 promise 如果没有返回的结果的时候 后面的代码一直处于等待中 不会执行
    • 当你等待的 promise 执行了resolve 或者reject的时候才表示等待到结果
async function fun(){
  let res=await new Promise((resovle,reject)=>{
    setInterval(()=>{
        console.log(1);
        resolve("aaa");
    },1000);
  });
  console.log(res);
  console.log(2);
}
fun();
//输出1 aaa 2 1 1 1 1 1 1 1....
            async function getData() {
                let res1 = await pAjax({
                    url: "./data1.php",
                });

                let res2 = await pAjax({
                    url: "./data2.php",
                    data: { num: res1 },
                });

                let res3 = await pAjax({
                    url: "./data3.php",
                    data: { num: res2 },
                });
                console.log(res3);
            }

            getData();
            //输出30
        </script>

瀑布流布局请求数据

<!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" />
        <meta name="referrer" content="no-referrer" />
        <title>Document</title>
        <style>
            * {
                margin: 0;
                padding: 0;
            }

            ul,
            li {
                list-style: none;
            }

            a,
            img {
                width: 100%;
                height: 100%;
                display: block;
            }

            .box {
                width: 1200px;
                margin: 0 auto;
            }

            ul {
                width: 260px;
                float: left;
                margin-right: 30px;
            }

            ul > li {
                width: 100%;
                display: flex;
                flex-direction: column;
                border: 1px solid #333;
                margin-top: 10px;
            }

            ul > li > .imgBox {
                width: 100%;
            }

            ul > li > .contentBox {
                height: 160px;
                box-sizing: border-box;
                padding: 10px;

                display: flex;
                flex-direction: column;
                justify-content: space-between;
            }

            ul > li > .contentBox > p {
                display: flex;
                justify-content: flex-start;
                align-items: center;
            }

            ul > li > .contentBox > p:nth-child(1) {
                display: -webkit-box;
                -webkit-line-clamp: 2;
                -webkit-box-orient: vertical;
                word-break: break-all;
                height: 40px;
                overflow: hidden;
            }

            ul > li > .contentBox > p:nth-child(2) > i {
                width: 10px;
                height: 10px;
                background-color: #bbb;
            }

            ul > li > .contentBox > p:nth-child(2) > span {
                color: #bbb;
                padding: 0 10px;
            }

            ul > li > .contentBox > p:nth-child(3) > span:nth-child(1) {
                width: 25px;
                height: 25px;
                border-radius: 50%;
                overflow: hidden;
            }

            ul > li > .contentBox > p:nth-child(3) > span:nth-child(2) {
                padding-left: 10px;
                display: flex;
                flex-direction: column;
            }

            ul > li > .contentBox > p:nth-child(3) .msg {
                display: inline-block;
                width: 100px;
                overflow: hidden;
                height: 18px;
                text-overflow: ellipsis;
                white-space: nowrap;
                font-weight: normal;
            }
        </style>

        <script src="../ajax/ajax.js"></script>
    </head>

    <body>
        <div class="box">
            <ul>
                <!-- <li>
                    <div class="imgBox">
                        <a href="javascript:;">
                            <img
                                src="https://c-ssl.duitang.com/uploads/item/201904/26/20190426233120_zxpmm.thumb.400_0.jpg"
                                alt=""
                            />
                        </a>
                    </div>
                    <div class="contentBox">
                        <p>
                            黑白线稿/橡皮章素材/动漫/魔道祖师/蓝忘机黑白线稿/橡皮章素材/动漫/魔道祖师/蓝忘机
                        </p>
                        <p>
                            <i></i>
                            <span>12</span>
                            <i></i>
                            <span>22</span>
                        </p>
                        <p>
                            <span>
                                <a href="javascript:;">
                                    <img
                                        src="https://c-ssl.duitang.com/uploads/people/201803/15/20180315202505_VsjC4.thumb.24_24_c.jpeg"
                                        alt=""
                                    />
                                </a>
                            </span>
                            <span>
                                <strong>name</strong>
                                <span>
                                    发布到
                                    <strong>位置</strong>
                                </span>
                            </span>
                        </p>
                    </div>
                </li> -->
            </ul>
            <ul></ul>
            <ul></ul>
            <ul></ul>
        </div>

        <script>
            /* 
                【1】获取页面中所需要的标签
                【2】根据接口获取数据
                【3】渲染数据 
                    1】判断4列的ul高,往高度最小的ul中添加数据
                【4】滚动滚动条的时候,当滚动条到达最小ul的高度的时候需要再次请求数据 
            */
            let uls = document.querySelectorAll(".box ul");
            let start = 0;
            // 设置一个变量表示 是否可以请求数据
            // 如果为true的时候表示可以请求数据
            let flag = true;
            ajax({
                url: "/dt",
                data: {
                    include_fields:
                        "top_comments%2Cis_root%2Csource_link%2Citem%2Cbuyable%2Croot_id%2Cstatus%2Clike_count%2Csender%2Calbum%2Creply_count",
                    filter_id: "%E6%89%8B%E5%B7%A5DIY",
                    start: start,
                },
                success: function (res) {
                    let data = JSON.parse(res);
                    console.log(data);
                    start = data.data.next_start;

                    render(data.data.object_list);
                },
            });

            // 滚动条滚动
            window.onscroll = function () {
                let minUl = getMinUl();
                let h = minUl.offsetHeight;

                if (scrollY >= h - innerHeight && flag == true) {
                    // 表示正在请求数据 不可以第二次请求
                    flag = false;
                    // console.log(1);
                    // 再次请求数据
                    ajax({
                        url: "/dt",
                        data: {
                            include_fields:
                                "top_comments%2Cis_root%2Csource_link%2Citem%2Cbuyable%2Croot_id%2Cstatus%2Clike_count%2Csender%2Calbum%2Creply_count",
                            filter_id: "%E6%89%8B%E5%B7%A5DIY",
                            start: start,
                        },
                        success: function (res) {
                            let data = JSON.parse(res);
                            start = data.data.next_start;

                            // 表示数据请求完成 可以进行一下次数据请求
                            flag = true;

                            render(data.data.object_list);
                        },
                    });
                }
            };

            function render(data) {
                data.forEach((item) => {
                    let str = `<li>
                        <div class="imgBox">
                            <a href="javascript:;">
                                <img
                                    src="${item.photo.path}"
                                    alt=""
                                />
                            </a>
                        </div>
                        <div class="contentBox">
                            <p>
                                ${item.msg}
                            </p>
                            <p>
                                <i></i>
                                <span>${item.favorite_count}</span>
                                <i></i>
                                <span>${item.like_count}</span>
                            </p>
                            <p>
                                <span>
                                    <a href="javascript:;">
                                        <img
                                            src="${item.sender.avatar}"
                                            alt=""
                                        />
                                    </a>
                                </span>
                                <span>
                                    <strong>${item.sender.username}</strong>
                                    <span>
                                        发布到
                                        <strong>${item.album.name}</strong>
                                    </span>
                                </span>
                            </p>
                        </div>
                    </li>`;

                    // 需要判断 ul的高度 得到一个最小高度的ul
                    // 假设第一个ul是最小
                    let minUl = getMinUl();

                    minUl.innerHTML += str;
                });
            }

            // 计算最小高度的ul
            function getMinUl() {
                let ul = uls[0];
                for (let i = 1; i < uls.length; i++) {
                    if (uls[i].offsetHeight < ul.offsetHeight) {
                        ul = uls[i];
                    }
                }
                return ul;
            }
        </script>
    </body>
</html>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值