Promise & jsonP
Promise
一、什么是promise?
是ES6提出的一种异步编程解决方案。它是一个构造函数Promise
二、语法:
//resolve : 成功 reject : 失败
new Promise((resolve,reject)=>{
//处理的异步程序
if(处理成功){
resolve();
}else{
reject();
}
});
三、方法
Promise.prototype.then : 当promise返回resolve状态时,可以调用then方法
Promise.prototype.catch : 当promise返回reject状态时,可以调用catch方法
四、Promise有三种状态
resolved : 成功
reject : 失败
pending : 进行中
五、 Promise的静态方法 Promise.all()
all : 当数组中所有返回的promise对象全部返回resolve状态时,当前all方法返回resolve.如果有一个promise对象返回reject,那么当前all方法返回reject.
当有多个异步程序时
new Promise((resolve,reject)=>{
if(){
resolve()
}else{
reject()
}
}).then(()=>{
return new Promies(){}
}).then(()=>{
return new Promise(){}
}).catch(()=>{})
应用
1.计时器回调函数
要实现3秒后输出数字3,2秒后输出数字2,1秒后输出数字1的效果,应为计时器是异步函数,如果不嵌套就会同时进行,必须嵌套使用才能实现我们上面的效果。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>01计时器回调函数</title>
</head>
<body>
<script>
setTimeout(() => {
alert(1);
setTimeout(() => {
alert(2);
setTimeout(() => {
alert(3);
},1000)
},2000)
},3000)
</script>
</body>
</html>
但是层级的回调嵌套会造成回调地狱。所以有了Promise来解决这个问题
2.计时器Promise
下面这个只是使用了一个Promise
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>03计时器promise</title>
</head>
<body>
<script>
new Promise((resolve,reject) => {
setTimeout(() => {
resolve();
},3000);
}).then(() => {
alert(3);
setTimeout(() => {
alert(2)
},2000);
})
</script>
</body>
</html>
3.计时器 Promise
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>05计时器promise</title>
</head>
<body>
<script>
new Promise((resolve,reject) => {
setTimeout(() => {
resolve();
},3000)
}).then(() => {
alert(3);
return new Promise((resolve,reject) => {
setTimeout(() => {
resolve();
},2000)
})
}).then(() => {
alert(2);
setTimeout(() => {
alert(1);
},1000)
})
</script>
</body>
</html>
4.ajax & 回调嵌套
ajax.js
let ajax = {};
ajax.get = function (url,fnWin,fnFail) {
var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
xhr.open('get',url,true);
xhr.send();
xhr.onreadystatechange = function () {
if(xhr.readyState === 4){
if(xhr.status === 200){
if(fnWin instanceof Function){
fnWin(xhr.responseText);
}
}else{
if(fnFail instanceof Function){
fnFail();
}
}
}
}
}
ajax.post = function (url,data,fnWin,fnFail) {
var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
xhr.open('post',url,true);
xhr.setRequestHeader('Content-type','Application/x-www-form-urlencoded;charset=utf-8');
xhr.send(data);
xhr.onreadystatechange = function () {
if(xhr.readyState === 4){
if(xhr.status === 200){
if(fnWin instanceof Function){
fnWin(xhr.responseText);
}
}else{
if(fnFail instanceof Function){
fnFail();
}
}
}
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>02ajax回调嵌套</title>
</head>
<body>
<script src="js/ajax.js"></script>
<script>
ajax.get('02text1.txt',data => {
ajax.get(data,data => {
ajax.get(data,data => {
alert(data);
})
})
})
</script>
</body>
</html>
5.ajax & promise
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>04ajax promise</title>
</head>
<body>
<script src="js/ajax.js"></script>
<script>
new Promise((resolve,reject) => {
ajax.get('02text1.txt',data => {
resolve(data);
})
}).then((data) => {
ajax.get(data,data => {
alert(data);
})
})
</script>
</body>
</html>
6.ajax & promise
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>06ajax promise</title>
</head>
<body>
<script src="js/ajax.js"></script>
<script>
new Promise((resolve,reject) => {
ajax.get('02text1.txt',(data) => {
resolve(data);
})
}).then((data) => {
return new Promise((resolve,reject) => {
ajax.get(data,data => {
resolve(data);
})
})
}).then(data => {
ajax.get(data,data => {
alert(data);
})
})
</script>
</body>
</html>
Ajax的同源策略
同源是指:同协议,同域名(主机名)和同端口。
当要访问不同域名,或者不同协议,或者不同端口的时候需要跨域访问。
跨域方式有
- 后端代理
- jsonP
- xhr2
- Nginx
jsonP(前端可以实现的跨域方式)
jsonP原理:
本质是利用了src跨域的特点。通过动态创建script标签,设置src属性为对方的接口地址,以get方式传递请求,并将响应的结果通过回调函数返回。
要主注意:回调函数必须是全局函数
使用jsonP实现淘宝的搜索下拉提示
思路:当我们在搜索框输入我们想要搜索的内容,键盘弹起的那一刻,下面出来一系列和我们搜索相关的提示,即键盘弹起事件。
当键盘弹起的时候,动态地创建一个script标签,并设置它的src属性值为我们提前在淘宝找好的接口地址,然后修改接口地址里面的两个地方,第一个是把关键字修改为当前文本输入框的值,第二个是回调函数的名字,修改为我们自己写的回调函数的名字。
例如,当我们在淘宝的输入框输入 hua ,然后我们在控制台找见一个接口地址为 https://suggest.taobao.com/sug?code=utf-8&q=hua&_ksTS=1600949240906_450&callback=jsonp451&k=1&area=c2c&bucketid=4 然后在里面找我们在输入框输入对的 hua,把这个值改为this.value,即我们在输入框输入的值;然后在接口地址中找见回调函数,一般为cb或者callback,把这个值修改为我们自己写的回调函数的名字。修改之后为:https://suggest.taobao.com/sug?code=utf-8&q=${this.value}&_ksTS=1600949240906_450&callback=fn&k=1&area=c2c&bucketid=4
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>jsonP</title>
<style>
input{
width: 300px;
height: 30px;
border: 2px solid orange;
border-radius: 15px;
outline: none;//去掉input控件的外边框
}
a{
text-decoration: none;
color: black;
font-weight: 900;
display: inline-block;
margin-bottom: 10px;
}
#box{
width: 305px;
height: 350px;
border: 2px solid gray;
/* display: none; */
}
</style>
</head>
<body>
<input type="text" name="" id="">
<div id="box"></div>
<script>
//jsonP前端跨域的方法,动态地创建script标签,利用其scr属性的跨域特点,设置src属性为对方的接口地址,一get方式传递请求,并将响应结果通过回调函数返回。要注意,回调函数必须是全局函数
//百度
// https://www.baidu.com/sugrec?pre=1&p=3&ie=utf-8&json=1&prod=pc&from=pc_web&sugsid=32617,1464,32328,31253,32723,7632,32115,32719,26350&wd=yi&req=2&csor=2&pwd=y&cb=jQuery1102009665188345799813_1600947605277&_=1600947605280
//淘宝
// https://suggest.taobao.com/sug?code=utf-8&q=hua&_ksTS=1600949240906_450&callback=jsonp451&k=1&area=c2c&bucketid=4
let o_box = document.querySelector('div');
let o_txt = document.querySelector('input');
// o_txt.onfocus =
o_txt.onkeyup = function(){
//每次按下都清空一下页面的内容
o_box.innerHTML = '';
//动态创建script
let o_scr = document.createElement('script');
// o_scr.src = `https://www.baidu.com/sugrec?pre=1&p=3&ie=utf-8&json=1&prod=pc&from=pc_web&sugsid=32617,1464,32328,31253,32723,7632,32115,32719,26350&wd=${this.value}&req=2&csor=2&pwd=y&cb=fn&_=1600947605280`;
o_scr.src = `https://suggest.taobao.com/sug?code=utf-8&q=${this.value}&_ksTS=1600949240906_450&callback=fn&k=1&area=c2c&bucketid=4`;
//把scrip标签放到head中
document.head.appendChild(o_scr);
}
function fn(data){
//回调函数带回来的数据打印一下,判断是什么类型的数据,然后确定要怎么获取
//百度 把获取到的内容输入在ul li 中
// console.log(data); //对象
//然后逐层找我们想要的数据
// console.log(data.g); //数组
//遍历数组
// data.g.forEach((value) => {
// // console.log(value.q); //我们想要的数据
// //创建li
// let o_li = document.createElement('li');
// o_li.innerHTML = '<a href="http://1000phone.com">' + value.q + '</a>';
// o_ul.appendChild(o_li);
// })
//淘宝
// console.log(data); //对象
//然后逐层找我们想要的数据
// console.log(data.result); //数组
//遍历数组
data.result.forEach((value) => {
// console.log(value[0]); //我们想要的数据
o_box.innerHTML += '<a href="http://1000phone.com">' + value[0] + '</a>' + '<br>';
// o_box.appendChild();
})
}
</script>
</body>
</html>