ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Day24--promise

2022-06-24 19:32:37  阅读:129  来源: 互联网

标签:console log script -- Day24 url promise res


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,--,Day24,url,promise,res
来源: https://www.cnblogs.com/bange-pla/p/16409997.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有