promise和jsonp
作者:互联网
promise和jsonp
ajax回顾:
核心对象: xmlhttprequest
步骤
1.创建对象
2.打开请求地址(设置请求方式 GET 和 POST)
3.发送请求
4.监听请求
5.在请求监听中获取数据
回调地狱
回调的函数的无限嵌套 导致代码的可读性和可维护性差 以及代码的可扩展性差(代码失去了价值)
//需求 从a接口里面查询 用户名是李四的id
//从b接口查询对应的id的商品
//从c接口查询对应的商品的ip的商品类型
// 伪代码
AjaxUtil.get('a',{username:'李四'},(res)=>{ //a接口通过传姓名 获取返回的id
AjaxUtil.get('b',{id:res.data.id},(res)=>{ //通过a接口返回的id 来获取对应的商品
AjaxUtil.get('c',{id:res.data.id},(res)=>{ //通过b接口返回的商品id 来获取对应的商品类型
console.log(res.data);
....
})
})
})
解决回调地狱
使用es6新增的promise对象
Promise对象
概述:
promise是es6新增的一个对象,他翻译为承诺,他有三种状态。promise设计为异步的。
等待状态 (不能做其他的事情)
成功状态 (有成功调用的方法)
失败状态 (有失败调用的方法)
示例
// 使用new关键词 里面传递的参数是一个方法 这个方法里面通常存储一些异步的操作
// resolve表示成功执行的方法 reject失败执行的方法
var promise = new Promise((resolve,reject)=>{
let timer = setTimeout(()=>{
console.log('hello');
//调用成功的方法 里面可以传参数
// resolve('成功')
reject('失败')
},2000)
})
then (resolve进入的方法)
//对应的promise对象有俩个方法 then 成功调用的方法 catch 失败调用的方法
//.then 在对应的resolve方法调用以后 .catch reject调用才能进入
promise.then((res)=>{
//在then里面的方法 里面的参数为resolve的传递的参数
console.log(res);
console.log('我执行完了');
})
catch (reject进入的方法)
promise.catch((err)=>{
//在catch里面的方法 里面的参数为reject的传递的参数
console.log(err);
})
finally (只要达到成功或者是失败调用的方法)
//不管成功还是失败都会调用的方法(没有值传递)
promise.finally(()=>{
console.log();
})
then catch finally 都是原型方法 Promise.prototype上面的方法
对象方法
Promise.reject() //返回的是一个promise对象(then获取的参数)
Promise.resolve() //返回的是一个promise对象(catch获取的参数)
Promise.all(promise数组) //返回也是一个promise数组 (并行执行 包含执行完成的)
Promise.race(promise数组) //返回的一个promise对象 (返回的是最先执行的promise)
//对象方法
Promise.reject('失败').catch((res)=>{
console.log(res);
}) //失败
Promise.resolve('成功').then((res)=>{
console.log(res);
}) //成功
var arr = Promise.all([promise1,promise2,promise3]) //当所有的执行完才返回结果(数组)
var promise4 = Promise.race([promise1,promise2,promise3]) //race竞速 谁先执行完就是谁
利用promise来解决回调地狱
1.通过在对应的.then方法里面进入返回一个新的promise对象的形式
//解决回调地狱的方案
promise1.then((res)=>{
console.log(res);
return new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log('jack');
resolve('jack的promise')
},1000)
})
}).then((res)=>{
console.log(res);
return new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log('吃饭了吗');
resolve('吃饭了的promise')
},1000)
})
}).then((res)=>{
console.log(res);
setTimeout(()=>{
console.log('你好');
},1000)
})
ES7新增 async(异步) await(等待)
async修饰方法 await修饰对应的promise的
1.async修饰的方法会返回一个promise对象
2.await只能在async里面使用 (他是用来修饰promise对象的)
3.await会让当前的主线程等待 (上锁)当你执行完成(成功了或者失败了)才放行(解锁)
//使用es7的 async以及await来简化代码
window.onload = async ()=>{
await new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log('hello');
resolve()
},1100)
})
await new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log('您好');
resolve()
})
})
console.log('执行完了');
}
使用promise封装对应的ajax
//xmlhttprequest有兼容 ie兼容 activeXObject
function initXhr(){
if(XMLHttpRequest){
return new XMLHttpRequest()
}
return new ActiveXObject("Micrisoft.XMLHTTP");//兼容ie6的
}
// 准备一个默认对象
var defaultObj = {
method:'get', //请求方式 默认为get
data:{}, //请求的数据 默认空对象
url:"", //请求的url地址 默认为空字符
dataType:"json", //请求过去的数据类型 默认为json
async:true //是否异步 默认为异步
}
//传递一个对象
//请求方式 method 请求的数据data 请求的地址 url 对应的请求的数据data-type 是否异步 async
function ajax(option={}){
//填值
for(var key in defaultObj){
//没有这个值进行填值 如果有这个就是返回本身
option[key]?option[key]:option[key]=defaultObj[key]
}
//判断地址不为空
if(option["url"]==""){
throw new Error('地址不能为空')
}
//判断请求的方法不是get获取post 报错
if(option["method"].toLowerCase()!='get' && option["method"].toLowerCase()!='post' ){
throw new Error('请求方式错误')
}
//区别 设置请求的时候 get指定(?拼接) post指定(请求体中)
let request = initXhr()
//指定请求
//如果是get先做数据拼接
if(option["method"].toLowerCase()=='get'){
//取出对应的数据进行拼接
for(let key in option["data"]){
if(option["url"].indexOf('?')!=-1){
option["url"] += `&${key}=${option["data"][key]}`
}else{
option["url"] += `?${key}=${option["data"][key]}`
}
}
request.open('get',option["url"])
//发送请求
request.send()
}else{//就是post请求
// request.setRequestHeader("Content-type","application/x-www-form-urlencoded");
request.open('post',option["url"])
request.setRequestHeader('Content-type',`application/${option["dataType"]}`)
//发送请求
request.send(JSON.stringify(option["data"]))
}
return new Promise((resolve,reject)=>{
// 监听请求
request.onreadystatechange = function(){
if(request.readyState == 4 && request.status==200){
// 返回数据
let obj = JSON.parse(request.responseText)
//成功响应出去
resolve(obj)
}
//状态码 200 - 299 时候返回一个错误
if(!/^2\d{2}$/.test(request.status)){
reject('请求出错')
}
}
})
}
调用
<script src="./promiseAjax.js"></script>
<script>
ajax({
url:"http://10.41.12.7:8080/shop",
data:{id:1}
}).then((res)=>{
console.log(res);
})
ajax({
url:"http://10.41.12.7:8080/user",
method:"post",
data:{username:'张三',password:'123'}
}).then((res)=>{
console.log(res);
})
</script>
同源策略
概述:同源策略是netspac提出一种安全策略,他是为了防止对应的后台被无限的访问(导致对应的安全问题)。他是指 域名相同(ip地址) 端口号相同 协议相同。
同源导致的问题(跨域 cors)
1.协议不同
2.端口号不同
3.ip地址不同
4.在ftp请求 资源不同也会跨域
解决跨域的问题
1.后台解决 (通过设置响应头)
Access-Control-All-Origin:* //所有都可以访问
Access-Control-All-Origin-Method:* //所有请求都可以访问
2.前台解决(通过对应的请求来设置对应的后台的响应)
3.前台解决 (通过jsonp来解决跨域 后台的配合)
4.代理 (我将对应你的访问作为我对应的服务器的代理)
跨域的根本是因为http协议(不走http协议 websocket (tcp协议))
JSONP
jsonp是一种跨域的解决方式 他需要后台的配合,对应的jsonp的核心是利用了对应html中带链接属性的标签的特性 (link script iframs..不受跨域影响的特性来解决对应的跨域问题 )这个里面的js代码不是浏览器本身在操作的而是后台通过服务器渲染来操作的
原理:利用script标签 链接这个地址 再将我们的回调函数做为参数传入
缺点:只支持get请求 (根本上就是一个get请求)
json入门案例(百度搜索)
<input type="text">
<ul></ul>
<script>
var ul = document.querySelector('ul')
//通过script链接对应的地址 传入对应的回调函数
//回调函数 console.log(res);
function fn(res){
ul.innerHTML = ""
console.log(res);
//遍历对应的res.s里面的数据 渲染到页面
// 创建li 填入ul
res.s.forEach(item => {
let li = document.createElement('li')
li.innerHTML = item
ul.appendChild(li)
});
}
//https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=miqi&cb=fn
document.querySelector('input').oninput = function(){
let keyWord = this.value
var path = "https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su"
//先出创建一个script标签
let tag = document.createElement("script")
tag.src = path+"?wd="+keyWord+'&cb=fn'
document.body.appendChild(tag)
//销毁
tag.remove()
}
</script>
jsonp封装
//封装对应的jsonp
static jsonp({
url, //请求的地址
param, //携带的参数 对象
callback,//执行的回调函数
callbackName //回调函数参数名
}){
//生成一个回调函数名字
let fnName = "fn"+ Date.now()
//指定的回调函数名字对应的方法 加给window
window[fnName] = callback
//创建script标签
var script = document.createElement('script')
//将回调函数 cb=fn加url
url += `?${callbackName}=${fnName}`
//将参数对象变成
for(let key in param){
url+=`&${key}=${param[key]}`
}
//再将对应的url地址给到script标签的src
script.src = url
//将srcipt加给body
document.body.appendChild(script)
//等待script标签加载完成
script.onload = function(){
//将script进行销毁
script.remove()
//将window属性删除
delete window[fnName]
}
}
调用
<input type="text">
<ul></ul>
<script src="./ajax.js"></script>
<script>
var ul = document.querySelector('ul')
//通过script链接对应的地址 传入对应的回调函数
//回调函数 console.log(res);
function fn(res){
ul.innerHTML = ""
console.log(res);
//遍历对应的res.s里面的数据 渲染到页面
// 创建li 填入ul
res.s.forEach(item => {
let li = document.createElement('li')
li.innerHTML = item
ul.appendChild(li)
});
}
//https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=miqi&cb=fn
// http://api.map.baidu.com/telematics/v3/weather
// https://api.douban.com/v2/movie/in_theaters
document.querySelector('input').oninput = function(){
let wd = this.value
AjaxUtil.jsonp({
url:"https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su",
param:{wd},
callback:fn,
callbackName:"cb"
})
}
</script>
jsonpPromise封装
function jsonp({
url, //请求的地址
param, //携带的参数 对象
callbackName //回调函数参数名
}){
return new Promise((resolve,reject)=>{
try { //捕获异常 可能出问题代码
//生成一个回调函数名字
let fnName = "fn"+ Date.now()
//指定的回调函数名字对应的方法 加给window
window[fnName] = resolve //填入resolve在then可以获取
//创建script标签
var script = document.createElement('script')
//将回调函数 cb=fn加url
url += `?${callbackName}=${fnName}`
//将参数对象变成
for(let key in param){
url+=`&${key}=${param[key]}`
}
//再将对应的url地址给到script标签的src
script.src = url
//将srcipt加给body
document.body.appendChild(script)
//等待script标签加载完成
script.onload = function(){
//将script进行销毁
script.remove()
//将window属性删除
delete window[fnName]
}
script.onerror = function(){
reject('当前请求错误')
}
} catch (error) { //处理对应的错误
reject(error)
}
})
}
调用
<input type="text">
<ul></ul>
<script src="./promiseAjax.js"></script>
<script>
var ul = document.querySelector('ul')
//通过script链接对应的地址 传入对应的回调函数
//https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=miqi&cb=fn
// http://api.map.baidu.com/telematics/v3/weather
// https://api.douban.com/v2/movie/in_theaters
document.querySelector('input').oninput = function(){
let wd = this.value
jsonp({
url:"https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su",
param:{wd},
callbackName:"cb"
}).then(res=>{
ul.innerHTML = ""
console.log(res);
//遍历对应的res.s里面的数据 渲染到页面
// 创建li 填入ul
res.s.forEach(item => {
let li = document.createElement('li')
li.innerHTML = item
ul.appendChild(li)
});
})
}
</script>
标签:console,log,script,url,res,promise,jsonp 来源: https://www.cnblogs.com/2323-qq/p/16417268.html