vue-promise-axios

 2023-09-10 阅读 23 评论 0

摘要:1 回调函数 1.1 回调函数定义: ① 函数是不是你定义的 你定义的 ② 函数你要有没有调用 你没调用 ③ 最终函数有没有被执行 最终执行了 1.2 回调函数分类: vue-property-decorator、同步的回调:数组api中的回调函数基本都是同步的;promise的执行器

1 回调函数

1.1 回调函数定义:

① 函数是不是你定义的 你定义的

② 函数你要有没有调用 你没调用

③ 最终函数有没有被执行 最终执行了

1.2 回调函数分类:

vue-property-decorator、同步的回调:数组api中的回调函数基本都是同步的;promise的执行器是同步的

异步的回调:定时器的回调 dom事件的回调 ajax请求的回调

遇到异步回调函数需注意以下两点:

① 回调什么时候进队列

vue-element?② 回调什么时候被执行

内存结构:堆 栈 队列

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2zfZO7rw-1626050796268)(D:\class\vue\02-vue\code\day07(axios)]\01_异步&单线程\定时器\事件循环模型.png)

//最快一秒钟同时输出5个5   
for (var i 0; i < 5; i++){setTimeout(function() {console.log(i)   55555},1000)
}
//...耗时的操作

2 变量的查找规则

  • js中的作用域就是函数作用域!

  • js promise?变量的查找基于作用域链

变量的查找规则:

① 左查询(变量出现在等号的左边使用左查询的规则进行变量查找)

​ 如果整条作用域链中 都没有对应变量的声明 则v8会默认在顶层作用域声明一份

vue trim。② 右查询(变量出现在等号的非左边使用右查询的规则进行变量查找)

​ 如果整条作用域链中 都没有对应变量的声明 则v8会报错

function wrap(){function inner(){a = 1;console.log(a,"inner")}inner()} wrap()console.log(a,"全局")  //1 inner 1 全局

3 Promis实例

3.1 Promise最佳实践

① promise实例是一次性的,一个promise实例实例只能使用一次

② promise构造函数的执行器必须有异步代码,应该在异步对应的回调来合理的调用resolve reject

axios vue、③ then方法中回调的返回值一般是一个新的promise

3.2 promise重点

① promise的实例对象三种状态是如何切换的 (成功 失败 初始化)

② promise的实例持有值为多少

当通过new Promise创造出来的promise实例; 他状态的改变以及持有的值 都跟执行器有关,new Promise时 执行器先执行 再返回promise实例。

vue then、执行器的返回值会被忽略

  • 如果执行器中什么都没有发生,创建出来的promise实例则是初始化状态,持有值是undefined
  • 如果执行器中resolve被调用,创建出来的实例是成功状态,持有的值是resolve函数第一个参数
  • 如果执行器中reject被调用,创建出来的实例是失败状态,持有的值是reject函数第一个参数
  • 如果执行器中发生异常,创建出来的promise实例是失败状态,持有的值是失败原因
    let promsie = new Promise((resolve, reject)=>{// 执行器内部的resolve, reject一定要放在一个异步环境下调用!!!setTimeout(()=>{resolve()},2000)})

promise是一个状态机,在promise状态改变时, 可以决定其then方法中的两个参数什么时候进队列,谁进队列。

then方法有两个参数是两个回调,这两个回调中的一个回调最终是要进队列的,至于是哪一个回调什么时候进队列取决用这个then方法的promise对象的状态什么时候发生改变,改变成什么状态

//此处代表执行时,promise处于初始化状态
let promise = promise.then(() =>{},()=>{})

then方法返回一个新的Promise,而它的行为与then中的回调函数的返回值有关:

  • vue v-for。如果then中的回调函数返回一个值,那么then返回的Promise将会成为成功状态,promise持有的值就是该返回值。

  • 如果then中的回调函数返回一个Promise,那么then返回的Promise会继承他的状态和值

  • 如果then中的回调函数抛出一个错误,那么then返回的Promise将会成为失败状态,promise持有的值就是错误原因

    //此处代表执行时,promise处于初始化状态
    promise.then(()=>{},()=>{})
    

4 promise面试题

    // 输出: 1 2 10 5 6 8 9 3//p2 创建完就是成功状态 持有的值为5//p1 创建完就是成功状态 持有的值为6//p3 创建完就是成功状态 持有的值为9const p1 = () => (new Promise((resolve, reject) => {console.log(1);let p2 = new Promise((resolve, reject) => {console.log(2);const timeOut1 = setTimeout(() => {console.log(3);resolve(4);}, 0)resolve(5);});resolve(6);p2.then((arg) => {console.log(arg);});}));const timeOut2 = setTimeout(() => {console.log(8);const p3 = new Promise(reject => {reject(9);}).then(res => {console.log(res)})}, 0)p1().then((arg) => {console.log(arg);});console.log(10);

5 async&await

async函数返回一个新的promise,而他的行为与async函数的代码体有关

  • 如果async函数代码体返回一个值,那么async函数返回的promise将会成为成功状态,promise持有的值就是该返回值
  • 如果async函数代码体返回一个promise,那么async函数返回的promise与当前代码体返回的promise一致
  • 如果async函数代码体抛出一个错误,那么async函数返回的promise将会成为失败状态,promise的值就是错误原因
//await等于一个promise,当等待的promise状态明确之后,async函数才会继续往下执行(async function(){try {const {data:{items}} = await axios.get("https://api.github.com/search/users?q=damu")let login = items[0].login;const {data:dataForRepos} = await axios.get(`https://api.github.com/users/${login}/repos`)let repname = dataForRepos[0].name;const data = await axios.get(`https://api.github.com/repos/${login}/${repname}/issues`)console.log(data)} catch(error) {console.log((error))}    })()

vue typescript,总结:

① async函数的执行结果是一个promise

② await通常等待是一个promise

async function getLogin(){const {data:{items}} = await axios.get("https://api.github.com/search/users?q=damu");	let  login = items[0].login;return login}
......
(async function (){const login = await getLogin()const repname = await getRepname(login)const data = await getIssues(login,repname)console.log(data);})()

6 axios

	axios.get("https://api.github.com/search/users?q=damu").then(({data:{items}}) =>{//console.log(items)   //得到所有带有damu名字的用户let login = items[0].login;return axios.get(`https://api.github.com/users/${login}/repos`)}).then(({data}) =>{//console.log(data)  //得到所有的仓库let login = data[0].owner.login;let repname = data[0].name;return axios.get(`https://api.github.com/repos/${login}/${repname}/issues`)}).then((data) => {console.log(data)  //得到仓库中的issues}).catch((err) =>{// 处理全程的异常处理,若有错误,异常穿透,打印错误信息console.log(err)})

axios

axios文档: http://www.axios-js.com/zh-cn/docs/
github开发者文档: https://docs.github.com/en根路径: https://api.github.com查询用户: https://api.github.com/search/users?q=damu查询指定用户的仓库:https://api.github.com/users/${login}/repos查询指定用户仓库的issues: https://api.github.com/repos/${login}/${repname}/issues

vue、安装axios:npm i axios

在项目的入口文件引入axios:import axios from “axios”

使用axios发生基本请求

7 restful 风格 api

7.1 code:

200:请求成功 返回内容
204:请求成功但不返回内容
403:权限不够,拒绝访问
404:接口未定义
412:params数据有问题
422:query数据有问题
500:服务器错误

7.2 method:

① get(查询 获取所有的issues) : /repos/{owner}/{repo}/issues

<div class="hello"><input type="text" v-model="username"><button @click="getIssues">获取仓库内容</button><ul v-if="issues.length" class="issues"><li v-for="issue in issues" :key="issue.id">{{issue.title}}:{{issue.body}}</li></ul></div>
import axios from "axios"
export default {name: 'issues',data() {return {issues:[],username:'betterDamu'  //输入框中的内容即是仓库名字}},methods:{// 获取仓库中的数据async getIssues(){const {data} = await axios({  ///repos/{owner}/{repo}/issuesurl:`https://api.github.com/repos/${this.username}/bj_181130/issues`,method:"get"})console.log(data)  //得到所有的仓库数据,可以结构赋值只拿到data数据this.issues = data},}
}

promise,② get(查询 获取指定的issues) : /repos/{owner}/{repo}/issues/{issue_number}

<a href="#" @click.prevent="getIssue(issue.number)">{{issue.title}}:{{issue.body}}</a>
// 点击获取仓库中的一个内容并输出async getIssue(issue_number) {const {data} = await axios({ //repos/{owner}/{repo}/issues/{issue_number}     url:`https://api.github.com/repos/${this.username}/bj_181130/issues/${issue_number}`,method:"get"})console.log(data)}

③ post(新增) : /repos/{owner}/{repo}/issues

新增接口,登录状态才能提问题,需要权限 github-setting-developer settings- personal access tokens

 <button @click="addIssue">给仓库增加一个内容</button>// 给仓库新增一个内容async addIssue() {const {data} = await axios({ //repos/{owner}/{repo}/issuesurl:`https://api.github.com/repos/${this.username}/bj_181130/issues`,method:"post",data:{title:"abc",body:"def",},headers:{Authorization:"token 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",}})//界面要刷新await this.getIssues()//.......必须要等界面刷新成功之后才能执行的后续逻辑}

④ patch(局部修改): /repos/{owner}/{repo}/issues/{issue_number}

<button @click="updateIssue(issue.number)">修改</button>// 进行局部更新 修改仓库中的一个内容async updateIssue(issue_number) {await axios({  ///repos/{owner}/{repo}/issues/{issue_number}url:`https://api.github.com/repos/${this.username}/bj_181130/issues/${issue_number}`,method:"patch",data:{title:"123456"},headers:{Authorization:"token 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",}})await this.getIssues()},

vue中promise的使用场景?⑤ put(锁) : /repos/{owner}/{repo}/issues/{issue_number}/lock

 <button @click="suoIssue(issue.number)"></button>async suoIssue(issue_number) { await axios({  ///repos/{owner}/{repo}/issues/{issue_number}url:`https://api.github.com/repos/${this.username}/bj_181130/issues/${issue_number}/lock`,method:"put",headers:{Authorization:"token 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",}})await this.getIssues()},

⑥ delete(解锁) : /repos/{owner}/{repo}/issues/{issue_number}/lock

<button @click="deleteIssue(issue.number)">解锁</button>async deleteIssue(issue_number) { await axios({  ///repos/{owner}/{repo}/issues/{issue_number}url:`https://api.github.com/repos/${this.username}/bj_181130/issues/${issue_number}/lock`,method:"delete",headers:{Authorization:"token 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",}})await this.getIssues()},

8 使用axios发送请求(实现对issues的CDUR)

8.1 通过axios函数发送请求

整个项目的所有模块使用同一个axios函数

import axios from "axios"
① axios (config) 
② axios(url,config) //config要删除URL配置config:{url:"请求方式",method:"请求方式",data:{} ,//请求体headers:{authorization},//请求头params:{},//这是query数据 query=paramstimeout:1000,//超时时间:请求发送的时间超过这个这个时间,会取消请求baseURL:基地址
}

8.2 请求方法的别名

③ axios.method(url,data,config)//config中要剔除url,method,data
 async getIssues(){const {data} = await axios.get(`https://api.github.com/repos/${this.username}/bj_181130/issues`,{  method:"get"})}

9 并发请求

axios.all(迭代器)
axios.spread(callback)
promise.all() 返回一个promise   建议用这个const data =  await Promise.all[axios1(),axios2()]   data[0]  axios1请求对应的数据data[1]  axios2请求对应的数据
	async created() {const data = await Promise.all([axios.get(`https://api.github.com/repos/betterdamu/bj_181130/issues`,{headers:{Authorization:"token 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"}}),axios.get(`https://api.github.com/search/users?q=damu`,{headers:{Authorization:"token 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"}})])console.log(data[0]); // 第一个请求的数据console.log(data[1]); // 第二个请求的数据}

10 创建实例

整个项目的所有模块可以使用不同axios实例来发送请求

src下新建一个api文件夹,文件issues.js 以下方法都支持:

① axios (config)

② axios(url,config) //config要删除URL配置

③ axios.method(url,data,config)//config中要剔除url,method,data

const ins = axios.create([config])
import axios from "axios";
const issuesAxios = axios.create({timeout:1000,baseURL:"https://api.github.com/",headers:{Authorization:"token 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"}
})// 添加请求拦截器
issuesAxios.interceptors.request.use(function (config) {// config.baseURL="https://api.zdy.com"return config;
});// 添加响应拦截器
issuesAxios.interceptors.response.use(function (response) {//响应回来的时 最早可以拿到返回数据的地方return response.data;
}, function (error) {//错误处理return Promise.reject(error);
});export default issuesAxios

11 axios返回数据的基本格式

{// `data` 由服务器提供的响应data: {},// `status` 来自服务器响应的 HTTP 状态码status: 200,// `statusText` 来自服务器响应的 HTTP 状态信息statusText: 'OK',// `headers` 服务器响应的头headers: {},// `config` 是为请求提供的配置信息config: {},// 'request'// `request` is the request that generated this response// It is the last ClientRequest instance in node.js (in redirects)// and an XMLHttpRequest instance the browserrequest: {}
}

12 axios配置优先级

优先级依次从低到高

全局默认

axios.defaults.baseURL = 'https://api.example.com';

实例特有

 axios.create({baseURL: 'https://api.example.com'});

发请求时确认

 instance.get('/longRequest', {baseURL: 'https://api.example.com'});

请求拦截器的第一个回调是最后可以修改配置的地方

13 拦截器

函数级别和实例级别都可以使用拦截器

// 添加请求拦截器    在app.vue函数级别的拦截器
axios.interceptors.request.use(function (config) {// 在发送请求之前做些什么return config;}, function (error) {// 对请求错误做些什么return Promise.reject(error);});// 添加响应拦截器
axios.interceptors.response.use(function (response) {// 响应回来的时候 最早可以拿到返回数据的地方return response;}, function (error) {// 对响应错误做点什么return Promise.reject(error);});

14 前端往后台传递数据的形式

url.params
url.query
body:请求头 一般只有post patch put来支持
headers:请求头

15 处理跨域

① 让所有的跨域请求改向webpack=dev-server代理服务器(它不光还具备静态资源管理的功能,还拥有转发请求的功能):一般都是修改请求的URL

② 设计webpack-dev-server的代理规则

​ 如果用的是vue-cli,这个配置在config/index.js文件中(dev-proxyTable)

③ 必要时要重写path

跨单域 congif-index.js

devServer: {proxy: {'/api': 'http://localhost:9000',},},

修改好后修改baseURL:

baseURL:"/api"  //以api开头的

跨多域

devServer: {proxy: {'/api': {  /api开头的,如/9000/apitarget: 'http://localhost:3000',pathRewrite: { '^/api': '' },},},},
 baseURL:"/9000"  //以9000开头的

项目上线时候,进行生产环境打包 npm dev build 只是在自己的webpackdevserver中,提醒运维做跨域处理

如果有coreURL,则优先使用coreURL 可以进行判断,若有跨域问题,优先使用coreURL ,否baseURL

16 axios二次封装

在项目中不会使用

src/api 文件夹

 contact(代表模块名称)axios.js :代表发送请求的工具config.js:代表发送请求的配置index.js :引入上述两个文件,再引入util中工具类, 生成所有的请求函数
github  
api.js :统筹所有模块的index.js,将所有的模块都暴露给ming.js

src/util

createForRequest.js 真正发请求的位置 核心代码

src/main.js

import api from "api/api"
Vue.prototype.$api = api

在项目中如何使用

请求相关的信息(URL methods等)还是不会直接出现在组件中,我们会创建一个叫api的目录,这个目录下会有很多模块发送请求的js文件,每个js文件往外暴露当前模块的请求函数(这些请求函数不是自动生成的,而是手动配置的)


17 mock数据

在没有后接口的情况下,如何造假数据(前后端分离)

17.1 通过webpack-dev-server(静态mock)

	//mock数据源 data:当前json的对象const appData = require("../data.json")const seller = appData.sellerconst goods = appData.goodsconst ratings = appData.ratingsdevServer:{before(app){  //before 是个钩子 app:express中的核心对象,可以注册后台路由//造一些假后台路由,其实没有真正的访问数据库,而是去拿json中数据//通过Ajax请求get方法来访问/api/seller,可以等得到对应的回调函数返回的数据app.get("/api/seller",(req,res)=>{ res.json({code:200,data:data.seller})})} }
//发送请求
async mounted() {axios({url:"/api/seller",method:get})console.log(data)
}

有后台接口之后,可以把before删掉。

此方法数据是静态的,一成不变的。

17.2 通过mock.js(动态mock)

文档地址:http://mockjs.com/ 生成随机数据,拦截ajax请求

① 安装

npm install mockjs -D

② 基本使用

// 使用 Mock
import Mock from 'mockjs'
var Mock = require('mockjs')  //生成随机数据,是以对象的形式出现
var data = Mock.mock({// 属性 list 的值是一个数组,其中含有 1 到 10 个元素'list|1-10': [{// 属性 id 是一个自增数,起始值为 1,每次增 1'id|+1': 1}]
})
// 输出结果
console.log(JSON.stringify(data))    

以上代码通过node mock.js来执行

③ 拦截ajax请求

在main.js中进行引入 mock.js

Mock.mock( template )根据数据模板生成模拟数据
Mock.mock( rurl, template ) 记录数据模板。当拦截到匹配 rurl 的 Ajax 请求时,将根据数据模板 template 生成模拟数据,并作为响应数据返回

自行去修改data.json中的数据,即是动态的

	const appData = require("../data.json")const seller = appData.sellerconst goods = appData.goodsconst ratings = appData.ratingsvar Mock = require('mockjs')  var data = Mock.mock({code:200,data:{'list|1-10': [{'id|+1': 1}]}
})

app.vue

//发送请求
async mounted() {axios({url:"/api/seller",method:get})console.log(data)
}

使用mock如何实现增删改查接口,mock静态页面模拟分页,可百度查

④ 语言规范

Mock.js 的语法规范包括两部分:
- 数据模板定义规范(Data Template Definition,DTD- 数据占位符定义规范(Data Placeholder Definition,DPD

⑤ DTD

数据模板中的每个属性由 3 部分构成:属性名、生成规则、属性值// name:属性名    rule:生成规则   value:属性值'name|rule': value
注意属性名 和 生成规则 之间用竖线 | 分隔生成规则 的 含义 需要依赖 属性值的类型 才能确定属性值 中可以含有 @占位符属性值 还指定了最终值的初始值和类型
规范地址https://github.com/nuysoft/Mock/wiki/Syntax-Specification              

⑥ DPD

占位符 只是在属性值字符串中占个位置,并不出现在最终的属性值中。
占位符 的格式为:@占位符     引用Mock.Random的方法city:“@city”   引用Mock.Random的方法生成随机城市
var Mock = require("mockjs")
console.log(Mock.Random) @表示调用randow方法

18 练习

npm i axios 配别名api和components

拆分组件 search.vue list.vue 在app.vue中引入,为了避免命名冲突,加v-search

在stasic中引入样式,并在index.html中引入当前的样式

在src下新建api,github.js文件 配置axios实例及公共配置,拦截器 并暴露出去

search.vue 中拿输入的内容 v-model,在main.js中注册总线(提供东西为触发事件),

点击search触发总线,把username输送出去,清除输入框,清除错误提示

list.vue中接收总线,随便在哪一个生命周期内都可以created,发送请求获取username对应的所有的GitHub用户 引入githubAxios 配置params

遍历list,拿头像和数据

扩展:当头像地址和名字接口变动的时候,不改模板,用map映射
含义 需要依赖 属性值的类型 才能确定
属性值 中可以含有 @占位符
属性值 还指定了最终值的初始值和类型
规范地址
https://github.com/nuysoft/Mock/wiki/Syntax-Specification

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/3/40120.html

上一篇:vuex-辅助函数
下一篇:react-state状态

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息