前端学习开发之【Promise】与【axios】
目录
- 0.补充
- 1. 实例对象与函数对象
- 2. 回调函数
- 3. 错误处理
- 1.概述
- 1. 简介
- 2. Promise状态
- 3. 使用Promise流程
- 4.使用util.pormisify(original)封装
- 5.封装AJAX请求
- 2.理论
- 1.Promise状态
- 2. Promise对象的值
- 3. API
- 4.关键问题
- 3.自定义Promise
- 4.async与await
- 1.async函数
- 2.await表达式
- 3. async与await结合实践
- 5.axios
- 1.简介
- 2.基本使用
- 3. axios请求方式
- 4.axios并发请求
- 5.全局配置
- 6.实例
- 7.拦截器
- 8.axios在vue中的模块封装
- 有能力再进行源码分析
0.补充
1. 实例对象与函数对象
实例对象:new函数产生的对象;
函数对象:把函数作为对象使用;(操作属性或方法)
2. 回调函数
自己定义的,但自己没有调用,依旧会执行。
同步回调:
立即执行,完全执行完了才结束。不会放入队列中。
异步回调:
放入队列中将来执行。一开始不直接干,启动之后直接往下执行,然后再执行该回调函数。
3. 错误处理
错误类型:
- ReferenceError:引用变量不存在;
- TypeError:数据类型不正确;(该类型不存在xxx属性或方法)
- RangeError:超出范围,死循环;
- SyntaxError:语法错误。
错误处理:
- 捕获错误:try catch 捕获error.message、stack
- 抛出错误:throw new Error(’ ')
错误对象:
message属性:错误相关信息;
stack属性:函数调用栈记录信息。
1.概述
1. 简介
异步编程:
- 文件操作
- 数据库操作
- 定时器
实现异步编程: 回调函数
什么是Promise?
Promise是JS中进行异步编程的解决方案,语法上讲就是一个构造函数,功能上讲promise对象用来封装一个异步操作并可以获取其成功或失败的结果值。
Promise 是一个 ECMAScript 6 提供的类,目的是更加优雅地书写复杂的异步任务。
为什么要用Promise:
- 指定回调函数,更灵活:启动异步任务—返回promise对象—给promise对象绑定回调函数;以前必须在启动异步任务前就把回调函数准备好;
- 支持链式调用,解决回调地狱问题(不断推进,一直嵌套)。
2. Promise状态
- pending变resolved
- pending 变 rejected
- Promise只有这两种状态,且一个对象只能改变一次;
- 无论成功还是失败,都只有一个结果数据;
- 成功结果为value,失败为reason。
流程:
3. 使用Promise流程
Promise是构造函数,可以实例化对象,接收的参数是函数类型的值,该函数有两个形参,resolve和reject(也是函数类型的数据),成功调用reslove,失败调用reject。
const p=new Promise((resolve,reject)=>{
//执行器函数 执行异步操作任务
//成功则调用resolve(value),将promise对象的状态设置为成功
//失败调用reject(reason),将promise对象的状态设置为失败
})
then方法:
接收两个参数,都是函数类型的值。成功则执行第一个回调函数,失败则执行第二个回调。
p.then(()=>{},()=>{})
4.使用util.pormisify(original)封装
传入一个错误优先的回调函数(即以(err,value)=>{}
回调作为最后一个参数),并返回一个promise的版本。
Node.js 内置的 util 模块有一个 promisify() ,该方法将基于回调的函数转换为基于 Promise 的函数。这使您可以将 Promise 链和 async/await 与基于回调的 API 结合使用。
//引入util模块
const util=require('util');
//引入fs模块
const fs=require('fs');
//返回一个新函数
let mineReadFile=util.promisify(fs.readFile);
mineReadFile('./resource/content.txt').then(value=>{});
5.封装AJAX请求
function sendAJAX(url){
return new Promise((resolve,reject)=>{
const xhr=new XMLHttpRequest();
xhr.open("GET",url);
xhr.send();
xhr.onreadystatechange=function(){
if(xhr.readystate===4){
if(xhr.status>=200&&xhr.status<300)
{
resolve(xhr.response);
}else{
reject(xhr.status);
}
}
}
}
sendAJAX('http://api')
.then(value=>{},reason=>{})
2.理论
1.Promise状态
实例对象中的一个属性 PromiseState
- pending 未决定的
- resolved、fullfilled 成功
- rejected 失败
一个promise对象只能改变一次,且只有一个数据结果,成功数据为value,失败数据为reason。
2. Promise对象的值
实例对象中的另一个属性 PromiseResult
保存着对象成功或失败的结果。
修改该值的函数:
- resolve;
- reject。
然后调用then方法对该值进行相关操作。
3. API
注意看清楚是属于函数对象,还是属于实例对象。
resolve:
如果传入参数为非Promise对象,则返回的结果为成功的promise对象;如果传入的参数为promise对象,则参数的结果为resolve的结果。
如果失败,需要用catch捕捉。
4.关键问题
如何改变promise状态:
- 调用resolve函数或reject函数;
throw ' '
抛出错误。
一个promise指定多个回调,都会调用吗:
- 当promise改变为对应状态时都会调用。
改变promise状态与指定回调函数的顺序问题:
- 都有可能,正常情况下先指定回调(then)再改变状态;
- 如何先改状态再指定回调:在执行器中直接调用resolve或reject;延迟调用then;
- 什么时候得到数据:先指定回调的话,当状态改变时,回调函数就会调用,得到数据;先改变状态的话,当指定回调时就会调用回调得到数据。
then返回promise对象的结果状态:
- 由then()指定的回调函数执行结果决定;
异常穿透:
前面抛出异常,可以在最后catch,中间可以调用then。
3.自定义Promise
使用:
let p=new Promise((resolve,reject)=>{
resolve('ok');
});
p.then(value=>{},reason=>{});
自定义:
- 定义整体结构:构造函数含执行器形参(函数类型),在原型链上添加then函数;构造函数中声明reject和resolve函数,并调用执行器,参数为reject和resolve;
- 设置reject和resolve函数:先添加属性PromiseState和PromiseResult并设置初始值;再保存实例对象this,然后在两函数中修改变量,(注意函数有形参data为结果值);
- throw抛出异常:调用执行器时使用try catch捕获异常,调用reject;
- 设置Promise状态只能修改一次:在reject和resolve函数中设置判断,若状态不为pending,则直接返回不进行修改操作;
- then方法执行回调:then方法有两个函数类型的形参onResolved和onRejected,当状态为fulfilled时调用前者,(形参为结果值);
- 异步任务回调的执行:为了能够在未改变状态时指定回调,需要在then中进行pending判断,增加callback变量,保存onRejected和onResolved两个回调函数;在构造函数的resolve和reject中增加调用回调;
- 指定多个回调的实现:callback修改为数组,可以push进多个对象,每个对象包含一个onResolved和一个onRejected;在resolve和reject函数中修改调用每一个回调;
- 同步任务修改状态 then方法结果返回:then的返回结果由回调函数的执行结果来决定,修改then函数,返回新建的Promise对象,如果结果是promise,则返回其then调用结果,如果不是promise对象,则调用resolve返回;
- 异步任务修改状态then方法结果返回:增加pending判断改为上述;
- then方法优化: 封装
hen的返回结果由回调函数的执行结果来决定,修改then函数,返回新建的Promise对象,如果结果是promise,则返回其then调用结果,如果不是promise对象,则调用resolve返回
; - catch方法(异常穿透与值传递):
- 封装resolve、reject、all、race函数;
- then方法回调函数异步执行:加上定时器;
- 封装成class:
function Promise(executor){
//添加属性
this.PromiseState='pending';
this.PromiseResult=null;
this.callbacks={};
//保存实例对象的this值
const self=this;
function resolve(data){
if(self.PromiseState !=='pending')return;
//1.修改对象状态(promiseState)
self.PromiseState='fulfilled';
//2.设置对象结果值(promiseResult)
self.PromiseResult=data;
setTimeout(()=>{
self.callbacks.forEach(item=>{
item.onResolved(data);
})
})
}
function reject(data){
if(self.PromiseState !=='pending')return;
//1.修改对象状态(promiseState)
self.PromiseState='rejected';
//2.设置对象结果值(promiseResult)
self.PromiseResult=data;
setTimeout(()=>{
self.callbacks.forEach(item=>{
item.onRejected(data);
})
})
}
try{
//同步调用执行器函数
excutor(resolve,reject);
}catch(e){
reject(e);
}
}
//形参为函数
Promise.prototype.then=function(onResolved,onRejected){
const self=this;
if(typeof onRejected !=='function'){
onRejected=reason=>{
throw reason;
}
}
if(typeof onResolved!=='function'){
onResolved=value=>value;
}
return new Promise((resolve,reject)=>{
//封装函数
function callback(type){
try{
let result=type(this.PromiseResult);
if(result istanceof Promise){
result.then(v=>{
resolve(v);
},r=>{
reject(r);
})
}else{
resolve(result);
}
}catch(e){
reject(e);
}
}
//调用回调函数
if(this.PromiseState==='fulfilled'){
setTimeout(()=>{
callback(onResolved);
})
}
if(this.PromiseState==='rejected'){
setTimeout(()=>{
callback(onRejected);
})
}
if(this.PromiseState==='pending'){
//保存回调函数
this.callbacks.push{
onResolved:function(){
callback(onResolved);
},
onRejected:function(){
callback(onRejected);
}
}
}
})
}
Promise.prototype.catch=function(onRejected){
return this.then(ondefined,onRejected);
}
Promise.resolve=function(value){
return new Promise((resolve,reject)=>{
if(value instanceof Promise){
value.then(v=>{
resolve(v)
},r=>{
reject(r);
}
}else{
resolve(value);
}
}
}
Promise.reject=function(reason){
return new Promise((resolve,reject)=>{
reject(reason);
}
}
Promise.all=function(promises){
return new Promise((resolve,reject)=>{
let count=0;
let arr=[];
for(let i=0;i<promises.length;i++){
promises[i].then(v=>{
count++;
arr[i]=v;
if(count===promises.length){
resolve(arr);
}
},r=>{
reject(r);
})
}
}
}
Promise.race=function(promises){
return new Promise((resolve,reject)=>{
for(let i=0;i<promises.length;i++){
promises[i].then(v=>{
resolve(v);
},r=>{
reject(r);
})
}
}
}
class Promise{
constructor(executor){
//添加属性
this.PromiseState='pending';
this.PromiseResult=null;
this.callbacks={};
//保存实例对象的this值
const self=this;
function resolve(data){
if(self.PromiseState !=='pending')return;
//1.修改对象状态(promiseState)
self.PromiseState='fulfilled';
//2.设置对象结果值(promiseResult)
self.PromiseResult=data;
setTimeout(()=>{
self.callbacks.forEach(item=>{
item.onResolved(data);
})
})
}
function reject(data){
if(self.PromiseState !=='pending')return;
//1.修改对象状态(promiseState)
self.PromiseState='rejected';
//2.设置对象结果值(promiseResult)
self.PromiseResult=data;
setTimeout(()=>{
self.callbacks.forEach(item=>{
item.onRejected(data);
})
})
}
try{
//同步调用执行器函数
excutor(resolve,reject);
}catch(e){
reject(e);
}
}
then((onResolved,onRejected){
const self=this;
if(typeof onRejected !=='function'){
onRejected=reason=>{
throw reason;
}
}
if(typeof onResolved!=='function'){
onResolved=value=>value;
}
return new Promise((resolve,reject)=>{
//封装函数
function callback(type){
try{
let result=type(this.PromiseResult);
if(result istanceof Promise){
result.then(v=>{
resolve(v);
},r=>{
reject(r);
})
}else{
resolve(result);
}
}catch(e){
reject(e);
}
}
//调用回调函数
if(this.PromiseState==='fulfilled'){
setTimeout(()=>{
callback(onResolved);
})
}
if(this.PromiseState==='rejected'){
setTimeout(()=>{
callback(onRejected);
})
}
if(this.PromiseState==='pending'){
//保存回调函数
this.callbacks.push{
onResolved:function(){
callback(onResolved);
},
onRejected:function(){
callback(onRejected);
}
}
}
})
}
catch(onRejected){
return this.then(ondefined,onRejected);
}
static resolve(value){}
static reject(reason){}
static all(promises){}
static race(promises){}
}
4.async与await
1.async函数
- 返回值为promise对象;
- promise对象的结果由async函数执行的返回值决定:如果返回值是一个非promise对象,则结果是成功状态的promise对象,结果值为return值;如果返回的结果是一个promise对象,则返回该对象;如果抛出异常,则返回一个失败的promise对象,结果值为抛出值。
2.await表达式
-
await右侧的表达式一般为promise对象,也可以为其他值;
-
如果表达式是promise对象,则await返回的是promise成功的结果值;
-
如果右侧是失败的promise对象,必须进行try catch捕获,得到失败的结果;
-
如果表达式是其他值,直接将此值作为await的返回值。
-
await必须写在async函数中,但async函数中可以没有await;
-
如果await的promise失败了,就会抛出异常,需要通过try catch捕获处理。
3. async与await结合实践
- 错误处理与回调更方便:直接try catch;
- 发送ajax时,直接调用封装好的函数。
5.axios
1.简介
axios是基于promise对ajax的封装。Axios 是一个基于 promise 网络请求库,作用于node.js 和浏览器中。 它是 isomorphic 的(即同一套代码可以运行在浏览器和node.js中)。在服务端它使用原生 node.js http 模块, 而在客户端 (浏览端) 则使用 XMLHttpRequests。
mvvm:
2.基本使用
默认使用get方式发送无参请求:
axios({
url:'https://api'
}).then(res=>{})
指定get方式发送无参请求:
axios({
url:'https://api',
method:'get'
}).then(res=>{})
指定post方式发送无参请求:
axios({
url:'https://api',
method:'post'
}).then(res=>{})
get发送有参请求:
axios({
url:'https://api?key=value',
method:'get'
}).then(res=>{})
axios({
url:'https://api',
params:{
key:'value',
},
method:'get'
}).then(res=>{})
post发送有参请求:
axios({
url:'https://api',
params:{
key:'value',
},
method:'post'
}).then(res=>{})
如果使用data而非params发送,则后台接收到的value为null,因为axios使用post携带参数默认使用application/json。
解决:1.使用params 2.服务器端给请求参数加上@requestBody。
3. axios请求方式
get无参:
axios.get('url').then(res=>{}).catch(err=>{})
get有参:
axios.get('url',{parmas:{key:'value'}}).then(res=>{}).catch(err=>{})
post无参:
axios.post('url').then(res=>{}).catch(err=>{})
post有参:
axios.post('url',"key=value&key2=value2").then(res=>{}).catch(err=>{})
使用data传输数据,后台需要将axuios自动转换成java对象,加上@requestBody。
4.axios并发请求
请求成功响应数组。
可以使用spread函数方法处理响应结果。
axios.all([
axios.get('url'),
axios.post('url')])
.then(
axios.spread((res1,res2)=>{})
).catch(err=>{})
5.全局配置
指定默认配置,它将作用于每个请求。
axios.defaults.baseURL='';
axios.defaults.timeout=2000;
6.实例
封装不同实例,实现不同配置
let newVar=axios.create({
baseURL:'',
timeout:5000
});
newVar({
url:''
}).then(res=>{})
7.拦截器
在发起请求或响应对操作进行处理,被 then 或 catch 处理前拦截它们。约等于过滤器
axios两大类拦截器:请求方向的拦截 响应方向拦截。
// 添加请求拦截器
axios.interceptors.request.use(config=>{
// 在发送请求之前做些什么
return config;
}, error=>{
// 对请求错误做些什么
return Promise.reject(error);
});
// 添加响应拦截器
axios.interceptors.response.use(response=>{
// 2xx 范围内的状态码都会触发该函数。
// 对响应数据做点什么
return response;
}, error=>{
// 超出 2xx 范围的状态码都会触发该函数。
// 对响应错误做点什么
return Promise.reject(error);
});
移除拦截器:
const myInterceptor = axios.interceptors.request.use(function () {/*...*/});
axios.interceptors.request.eject(myInterceptor);
8.axios在vue中的模块封装
- 安装
npm install --save
- 创建request文件夹存放请求函数;
- 封装。
传递参数:
import axios from 'axios';
export function request(config,success,fail){
axios({
url:config
}).then(res=>{success();})
.catch(err=>{fail();})
}
export function request1(config){
axios.defaults,baseURL='';
axios(config).then(res=>{config.success(res);})
.catch(err=>{config.fail(err);})
// config={url:'',success:res=>{},fail:err=>{}}
}
promise:
export function request(config){
return new Promise((resolve,reject)=>{
let newVar=axios.create({
baseURL:'',
timeout:5000
});
newVar(config).then(res=> {resolve(res);}).catch(err=>{reject(err);})
})
}
//调用
request({url:''}).then(res=>{}).catch(err=>{})
创建实例:
export function request(config){
let newVar=axios.create({
baseURL:'',
timeout:5000
});
return newVar(config);
}
request({
url:''}).then(res=>{})
2301_80439815: 最后那句其实就是没绷住
CSDN-Ada助手: 你好,CSDN 开始提供 #论文阅读# 的列表服务了。请看:https://blog.csdn.net/nav/advanced-technology/paper-reading?utm_source=csdn_ai_ada_blog_reply 。如果你有更多需求,请来这里 https://gitcode.net/csdn/csdn-tags/-/issues/34?utm_source=csdn_ai_ada_blog_reply 给我们提。
十分谔谔: 请问为什么通过最小化损失函数,模型将倾向于使c=0
Kwan的解忧杂货铺@新空间代码工作室: 博主的文章总是让人受益匪浅,知识的分享太有价值了,期待你继续灌输智慧!博主的文字清晰明了,让我在这个领域更加有信心,真的谢谢你的辛勤付出。
咔叽布吉: 如果你说的初始特征是编码器提取的特征的话:解码器的每一个模块的最后一步都是上/下采样让尺度匹配,RA模块中有卷积操作让通道数匹配。code中都有,可以看一下