① 函数是不是你定义的 你定义的
② 函数你要有没有调用 你没调用
③ 最终函数有没有被执行 最终执行了
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)
}
//...耗时的操作
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 全局
① promise实例是一次性的,一个promise实例实例只能使用一次
② promise构造函数的执行器必须有异步代码,应该在异步对应的回调来合理的调用resolve reject
axios vue、③ then方法中回调的返回值一般是一个新的promise
① promise的实例对象三种状态是如何切换的 (成功 失败 初始化)
② promise的实例持有值为多少
当通过new Promise创造出来的promise实例; 他状态的改变以及持有的值 都跟执行器有关,new Promise时 执行器先执行 再返回promise实例。
vue then、执行器的返回值会被忽略
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(()=>{},()=>{})
// 输出: 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);
async函数返回一个新的promise,而他的行为与async函数的代码体有关
//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);})()
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发生基本请求
200:请求成功 返回内容
204:请求成功但不返回内容
403:权限不够,拒绝访问
404:接口未定义
412:params数据有问题
422:query数据有问题
500:服务器错误
① 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()},
整个项目的所有模块使用同一个axios函数
import axios from "axios"
① axios (config)
② axios(url,config) //config要删除URL配置config:{url:"请求方式",method:"请求方式",data:{} ,//请求体headers:{authorization},//请求头params:{},//这是query数据 query=paramstimeout:1000,//超时时间:请求发送的时间超过这个这个时间,会取消请求baseURL:基地址
}
③ 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"})}
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]); // 第二个请求的数据}
整个项目的所有模块可以使用不同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
{// `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: {}
}
优先级依次从低到高
全局默认
axios.defaults.baseURL = 'https://api.example.com';
实例特有
axios.create({baseURL: 'https://api.example.com'});
发请求时确认
instance.get('/longRequest', {baseURL: 'https://api.example.com'});
请求拦截器的第一个回调是最后可以修改配置的地方
函数级别和实例级别都可以使用拦截器
// 添加请求拦截器 在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);});
url.params
url.query
body:请求头 一般只有post patch put来支持
headers:请求头
① 让所有的跨域请求改向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
在项目中不会使用
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文件往外暴露当前模块的请求函数(这些请求函数不是自动生成的,而是手动配置的)
在没有后接口的情况下,如何造假数据(前后端分离)
//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删掉。
此方法数据是静态的,一成不变的。
文档地址: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来执行
在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)
数据模板中的每个属性由 3 部分构成:属性名、生成规则、属性值// name:属性名 rule:生成规则 value:属性值'name|rule': value
注意属性名 和 生成规则 之间用竖线 | 分隔生成规则 的 含义 需要依赖 属性值的类型 才能确定属性值 中可以含有 @占位符属性值 还指定了最终值的初始值和类型
规范地址https://github.com/nuysoft/Mock/wiki/Syntax-Specification
占位符 只是在属性值字符串中占个位置,并不出现在最终的属性值中。
占位符 的格式为:@占位符 引用Mock.Random的方法city:“@city” 引用Mock.Random的方法生成随机城市
var Mock = require("mockjs")
console.log(Mock.Random) @表示调用randow方法
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
版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。
工作时间:8:00-18:00
客服电话
电子邮件
admin@qq.com
扫码二维码
获取最新动态