Jsonp和Promise-基础

一、JSONP
  1. 什么是JSONP? (解决跨域访问问题)
    JSONP让网页从别的地址(跨域的地址)那获取资料,即跨域读取数据;
  2. JSONP实现跨域访问的原理
    2.1在同一界面中可以定义多个 script 标签
    2.2同一个界面中多个script标签中的数据可以相互访问
    2.3可以通过script的src属性导入其它资源
    2.4通过src属性导入其它资源的本质就是将资源拷贝到script标签中
    2.5script的src属性不仅能导入本地资源, 还能导入远程资源
    2.6由于script的src属性没有同源限制, 所以可以通过script的src属性来请求跨域数据
<script src="20-jsonp.js">
    // let num = 777;
    // function test() {
    //     console.log("test777");
    // }
</script>
<script>
      console.log(num);   //  777
      test();   //  test777
</script>

1、JSONP优化

优化一
1.在企业开发中通过JSONP来获取跨域的数据,
一般情况下服务器返回的都不会是一个变量, 而是一个函数的调用

优化二
2.当前服务器返回的函数调用名称写死了
服务器返回函数叫什么名称, 我们本地就必须定义一个叫什么名称的函数

解决方案:
通过URL参数的方式来动态指定函数名称

优化三
3.由于script标签默认是同步, 前面的script标签没有加载完数据, 后面的script标签就不会被执行;
所以请求数据的script标签必须放到后面

解决方案:
通过JS动态创建script标签, 因为JS动态创建的script标签默认就是异步的,
不用等到前面的标签加载完就可以执行后面的script标签

let oScript = document.createElement("script");
oScript.src = "http://127.0.0.1:80/jQuery/Ajax/20-jsonp.php?cb=test";
document.body.appendChild(oScript);
function test(data) {
     console.log(data);
 }

2、jQuery中jsonp使用 (解决跨域问题)
$.ajax({
        url: "http://127.0.0.1:80/jQuery/Ajax/22-jsonp.php",  // 请求资源的地址
        
     // 主要是加了下面这句代码:
        dataType: "jsonp", // 告诉jQuery需要请求跨域的数据
        
        jsonp: "cb",  // 告诉jQuery服务器在获取回调函数名称的时候需要用什么key来获取,了解即可
        jsonpCallback: "lnj", // 告诉jQuery服务器在获取回调函数名称的时候回调函数的名称是什么,了解即可
        success: function (msg) {  // 把服务器返回的数据放入msg中;
            console.log(msg);
        }
    });

3、JS是单线程的:
  1. JS是单线程的
    所以JS中的代码都是串行的, 前面没有执行完毕后面不能执行;
  2. 同步代码和异步代码
    除了"事件绑定的函数"和"回调函数"以外的都是同步代码
    2.1程序运行会从上至下依次执行所有的同步代码
    2.2在执行的过程中如果遇到异步代码会将异步代码放到事件循环中
    2.3当所有同步代码都执行完毕后, JS会不断检测 事件循环中的异步代码是否满足条件
    2.4一旦满足条件就执行满足条件的异步代码

2.为什么JS是单线程的?
javaScript的单线程,与它的用途有关。
作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。
这决定了它只能是单线程,否则会带来很复杂的同步问题。

例如: 如果JS是多线程的
现在有一个线程要修改元素中的内容, 一个线程要删除该元素, 这时浏览器应该以哪个线程为准?

举例:

console.log("1"); // 同步代码
    setTimeout(function () { // 异步代码
        console.log("2");
    }, 500);
    console.log("3"); // 同步代码
    alert("666"); // 同步代码
    
   //     输出1 / 3 / 2

扩展阅读: https://segmentfault.com/a/1190000015042127


二、promise基本概念

1.什么是promise?
promise是ES6中新增的异步编程解决方案, 在代码中的表现是一个对象;

2.promise作用
企业开发中为了保存异步代码的执行顺序, 那么就会出现回调函数层层嵌套;
如果回调函数嵌套的层数太多, 就会导致代码的阅读性, 可维护性大大降低;
promise对象可以将异步操作以同步流程来表示, 避免了回调函数层层嵌套(回调地狱);


1、 promise基本使用

1.什么是Promise?
Promise是ES6中新增的一个对象,
通过Promise就可以实现 用同步的流程来表示异步的操作;
通过Promise就可以 避免回调函数层层嵌套(回调地狱)问题;

2.如何创建Promise对象?
new Promise(function(resolve, reject){});
promise对象不是异步的, 只要创建promise对象就会立即执行存放的代码;

3.Promise是如何实现 通过同步的流程来表示异步的操作的?
promise对象是通过状态的改变来实现的, 只要状态发生改变就会自动触发对应的函数;

4.Promise对象三种状态
pending: 默认状态,只要没有告诉promise任务是成功还是失败就是pending状态;
fulfilled(resolved): 只要调用resolve函数, 状态就会变为fulfilled, 表示操作成功;
rejected: 只要调用rejected函数, 状态就会变为rejected, 表示操作失败;
注意点: 状态一旦改变既不可逆, 即从pending变为fulfilled, 那么永远都是fulfilled;
即从pending变为rejected, 那么永远都是rejected;

5.监听Promise状态改变
我们还可以通过函数来监听状态的变化
resolved --> then()
rejected --> catch()


2、promise-then方法

1. then方法
then方法接收两个参数,
第一个参数是状态切换为成功时的回调,
第二个参数是状态切换为失败时的回调

let promise = new Promise(function (resolve, reject) {
        // resolve(); // 将状态修改为成功
        reject(); // 将状态修改为失败
    });
    promise.then(function () {
        console.log("成功");
    }, function () {
        console.log("失败");
    });

2. then方法
在修改promise状态时, 可以传递参数给then方法中的回到函数

let promise = new Promise(function (resolve, reject) {
        // resolve("111"); // 将状态修改为成功 success("111");
        reject("aaa"); // 将状态修改为失败  error("aaa");
    });
    // promise.then(function (data) {
    //     console.log("成功", data);
    // }, function (data) {
    //     console.log("失败", data);
    // });

3. then方法
同一个promise对象可以多次调用then方法,
当该promise对象的状态时所有then方法都会被执行

let promise = new Promise(function (resolve, reject) {
        // resolve(); // 将状态修改为成功
        reject(); // 将状态修改为失败
    });
    promise.then(function () {
        console.log("成功1");
    }, function () {
        console.log("失败1");
    });
    promise.then(function () {
        console.log("成功2");
    }, function () {
        console.log("失败2");
    });

4. then方法
then方法每次执行完毕后会返回一个新的promise对象

  let promise = new Promise(function (resolve, reject) {
        resolve(); // 将状态修改为成功
        // reject(); // 将状态修改为失败
    });
    let p2 = promise.then(function () {
        console.log("成功1");
    }, function () {
        console.log("失败1");
    });
    console.log(p2);
    console.log(promise === p2);

5. then方法
可以通过上一个promise对象的then方法给下一个promise对象的then方法传递参数
注意点:
无论是在上一个promise对象成功的回调还是失败的回调传递的参数,都会传递给下一个promise对象成功的回调;

let promise = new Promise(function (resolve, reject) {
        // resolve("111"); // 将状态修改为成功
        reject("aaa"); // 将状态修改为失败
    });
    let p2 = promise.then(function (data) {
        console.log("成功1", data);
        return "222";
    }, function (data) {
        console.log("失败1", data);
        return "bbb";
    });
    p2.then(function (data) {
        console.log("成功2", data);
    }, function (data) {
        console.log("失败2", data);
    });


let promise = new Promise(function (resolve, reject) {
        resolve("111"); // 将状态修改为成功
        // reject("aaa"); // 将状态修改为失败
    });
    let ppp = new Promise(function (resolve, reject) {
        // resolve("222"); // 将状态修改为成功
        reject("bbb"); // 将状态修改为失败
    });
    let p2 = promise.then(function (data) {
        console.log("成功1", data);
        return ppp;
    }, function (data) {
        console.log("失败1", data);
        return "bbb";
    });
    p2.then(function (data) {
        console.log("成功2", data);
    }, function (data) {
        console.log("失败2", data);
    });

3、promise-catch方法

1. catch方法
catch 其实是 then(undefined, () => {}) 的语法糖

2. catch方法
注意点: 如果需要分开监听, 也就是通过then监听成功通过catch监听失败
那么必须使用链式编程, 否则会报错、

let promise = new Promise(function (resolve, reject) {
        // resolve(); // 将状态修改为成功
        reject(); // 将状态修改为失败
    });
    // promise.then(function () {
    //     console.log("成功");
    // }).catch(function () {
    //     console.log("失败");
    // });

3. catch方法
不使用链式编程的原因是
1.如果promise的状态是失败, 但是没有对应失败的监听就会报错
2.then方法会返回一个新的promise, 新的promise会继承原有promise的状态
3.如果新的promise状态是失败, 但是没有对应失败的监听也会报错


1.catch方法
和then一样, 在修改promise状态时, 可以传递参数给catch方法中的回到函数

2.catch方法
和then一样, 同一个promise对象可以多次调用catch方法,
当该promise对象的状态时所有catch方法都会被执行

3.catch方法
和then一样, catch方法每次执行完毕后会返回一个新的promise对象

4.catch方法
和then方法一样, 上一个promise对象也可以给下一个promise成功的传递参数
注意点:
无论是在上一个promise对象成功的回调还是失败的回调传递的参数,
都会传递给下一个promise对象成功的回调

5.catch方法
和then一样, catch方法如果返回的是一个Promise对象, 那么会将返回的Promise对象的
执行结果中的值传递给下一个catch方法

6.catch方法
和then方法第二个参数的区别在于, catch方法可以捕获上一个promise对象then方法中的异常

let promise = new Promise(function (resolve, reject) {
        resolve();
    });
    
    promise.then(function () {
        console.log("成功");
        xxx
    }).catch(function (e) {
        console.log("失败", e);
    });

其他参考资料:https://www.imooc.com/article/36750?block_id=tuijian_wz


4、异常处理
  1. JS中的异常
    简单粗暴就是有错误出现
    由于JS是单线程的, 编写的代码都是串行的,
    所以一旦前面代码出现错误,程序就会被中断, 后续代码就不会被执行

  2. JS中的异常处理
    2.1自身编写代码问题, --> 手动修复BUG
    2.2外界原因问题, --> try{}catch{}
    对于一些可预见的异常, 我们可以使用try{}catch{}来处理,

  3. JS中如何进行异常处理
    利用try{}catch{}来处理异常可以保证程序不被中断, 也可以记录错误原因以便于后续优化迭代更新
    try {
    可能遇到的意外的代码
    }
    catch(e) {
    捕获错误的代码块
    }

例:

console.log("1");
    try {
        say();  // 未定义,会报错,但后边代码能继续执行
    }catch (e) {
        console.log(e);
    }
    console.log("2");

5、promise-all方法

需求:
1.无序加载图片, 每加载成功一张就添加一张
2.无序加载图片, 只有所有图片都加载成功才添加, 有一张图片失败都不添加

  1. Promise的all静态方法:
    1.all方法接收一个数组;
    2.如果数组中有多个Promise对象,只有都成功才会执行then方法, 并且会按照添加的顺序, 将所有成功的结果重新打包到一个数组中返回给我们;
    3.如果数组中不是Promise对象, 那么会直接执行then方法;

  2. Promise的all静态方法特点
    1.1all方法会返回一个新的Promise对象
    1.2会按照传入数组的顺序将所有Promise中成功返回的结果保存到一个新的数组返回
    1.3数组中有一个Promise失败就会失败, 只有所有成功才会成功

    应用场景: 批量加载, 要么一起成功, 要么一起失败

let arr = [
        "http://www.it666.com/files/system/block_picture_1555415767.png",
        "http://www.it666.com/files/system/block_picture_1555422597.jpg",
        "http://www.it666.com/files/system/block_picture_1555419713.jpg"
    ];

function loadImage(url) {
        return new Promise(function (resolve, reject) {
            let oImg = new Image();
            let time = Math.random() * 1000;
            // console.log(time);
            setTimeout(function () {
                oImg.src = url;
            }, time);
            // oImg.src = url;
            oImg.onload = function () {
                resolve(oImg);
            }
            oImg.onerror = function () {
                reject("图片加载失败了");
            }
        });
    }

Promise.all([loadImage(arr[0]), loadImage(arr[1]),loadImage(arr[2])])
        .then(function (result) {
            // console.log(result);
            result.forEach(function (oImg) {
                document.body.appendChild(oImg);
            });
        })
        .catch(function (e) {
            console.log(e);
        });

7、promise-race方法

Promise的race静态方法:
1.all方法接收一个数组,
2.如果数组中有多个Promise对象, 谁先返回状态就听谁的, 后返回的会被抛弃
3.如果数组中不是Promise对象, 那么会直接执行then方法

应用场景: 接口调试, 超时处理

let url = "http://www.it666.com/files/system/block_picture_1555415767.png";
 function loadImage(url) {
     return new Promise(function (resolve, reject) {
         let oImg = new Image();
         setTimeout(function () {
             oImg.src = url;
         }, 5000);
         oImg.onload = function () {
             resolve(oImg);
         }
         oImg.onerror = function () {
             reject("图片加载失败了");
         }
     });
 }
 function timeout() {
     return new Promise(function (resolve, reject) {
         setTimeout(function () {
             reject("超时了");
         }, 3000);
     });
 }
 Promise.race([loadImage(url), timeout()]).then(function (value) {
     console.log("成功", value);
 }).catch(function (e) {
     console.log("失败", e);
 });


-End

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值