回调地狱
封装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.")";
网友评论