AJAX和Promise及跨域

回调地狱

封装ajax的时候,发现:请求成功后的值不能直接返回给调用者,而需要在其内部执行一个回调函数。如果在请求一次后需要再次请求,那么,也就是在回调函数中需要再次调用ajax,再次传入回调函数,次数多了以后就形成了回调地狱。难以使用及维护

回调地狱

解决:es6中的构造函数Promise解决这个问题。

基本语法:

new Promise(function (resolve, reject) {
                      // resolve 表示成功的回调
                      // reject 表示失败的回调
                }).then(function (res) {
                      // 成功的函数
                }).catch(function (err) {
                      // 失败的函数
                })

在promise中,提供了两个参数,分别表示执行成功和失败的回调函数,执行成功调用resolve,失败调用reject即可,具体resolve和reject的执行,分别在then和catch中。这样可以将回调函数变成链式结构,从而解决了回调地狱的问题。
案例:

new Promise(function (resolve, reject) {
        ajax({
            url: '第一个请求',
            success(res) {
                resolve(res)
            }
        })
    }).then(function (res) {
        // 准备发送第二个请求
        return new Promise(function (resolve, reject) {
            ajax({
                url: '第二个请求',
                data: { a: res.a, b: res.b },
                success(res) {
                    resolve(res)
                }
            })
        })
    }).then(function (res) {
        ajax({
            url: '第三个请求',
            data: { a: res.a, b: res.b },
            success(res) {
                console.log(res)
            }
        })
    }).catch(function (res) {
    })

then和catch不会同时触发,也就是说,只要一个then出错了,执行最底下的catch就行,所以也就可以连续写多个then,一个catch就行

终极解决方案:es7提供的async/await

可以将异步代码写的和同步代码一样
语法:

  asyncfunctionfn() {
                    constres=awaitpromise对象
                }

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

async function fn() {
        const res = new Promise(function (resolve, reject) {
            ajax({
                url: '第一个地址',
                success(res) {
                    resolve(res)
                }
            })
        })
        // res 就可以得到请求的结果
        const res2 = new Promise(function (resolve, reject) {
            ajax({
                url: '第二个地址',
                data: { a: res.a, b: res.b },
                success(res) {
                    resolve(res)
                }
            })
        })
        const res3 = new Promise(function (resolve, reject) {
            ajax({
                url: '第三个地址',
                data: { a: res2.a, b: res2.b },
                success(res) {
                    resolve(res)
                }
            })
        })
        // res3 就是我们要的结果
        console.log(res3)
    }

跨域

原因是浏览器的同源策略
跨域:前端是不能跨域的,但是后端的语言可以。
概念:浏览器有同源策略,禁止ajax从一个域名请求另外一个域名上的数据,如果从一个域名请求另外一个域名上的数据,就是跨域

那什么是同源策略,所谓同源,就是指域名、协议、端口都相同。比如说:一个浏览器打开百度的网站,然后在控制台请求腾讯的网页,浏览器会报一个不是同源的异常。
解决:

  • 1.php解决跨域:
    也就是说跨域请求只是限制客户端向服务端,如果是服务端向服务端请求的话就不存在这个问题,也就是说需要跨域的请求交给php服务端来做,有了结果再响应给ajax即可。
    原理上利用的php的爬虫技术。有file_get_contents()、curl、ob_get_contents()
    在服务端设置响应头,允许跨域请求
    如果请求的服务端是自己可操作的话,可以在php端设置允许跨域的响应头。代码如下:header("Access-Control-Allow-Origin:*");
  • 2.配置nginx代理:
location = 自定义url {
proxy_pass 待跨域请求的地址
}
  • 3.通过jsonp来实现:
    利用标签可以跨域(当前网页的图片链接可以是别的网站上的图片)的特性,制作标签进行跨域
var script = document.createElement('script');
    script.setAttribute('src', "http://www.php.com/test.php?callback=response");
    $('head').append(script);
    function response(res) {
        $('#result').text(res);
    }
    // php代码:
    $fun = $_GET['callback'];
    echo "$fun(".$str.")";

你可能感兴趣的:(AJAX和Promise及跨域)