【Vue框架】Vue2中axios发送请求—安装axios、配置全局域名、传递参数、axios原理之Promise(什么是Promise、使用原因、基本使用、相关API、async与await使用)

2024-01-10 11:02:02 作者:欧亿体育

文章目录

一、axios 发送HTTP请求

官网: https://www.axios-http.cn/

1.1 安装axios

1.1.1 安装axios库

安装 axios 通信库:npm install axios -S

1.1.2 在全局中引入axios库

全局在main.js中引入axios: import axios from 'axios'

1.1.3 挂在原型对象

Vue.prototype.$axios = axios;
将 axios 挂载到Vue原型对象中,实现数据共享,节约内存空间。
此时在任何页面都可以使用axios获取数据。

03myaxios.vue

<template>
  <div>
    <h1>axios</h1>
  </div>
</template>

<script>
  export default {

  }
</script>

<style scode>

</style>

路由配置:router/index.js

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import tab from '../components/01tab.vue'
import login from '../components/login.vue'
import mycar from '../components/mycar.vue'
import mydetail from '../components/mydetail.vue'
import myorder from '../components/myorder.vue'
import myaxios from '../components/03myaxios.vue'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld
    },
    {
      path: '/tab',
      name: 'tab',
      component: tab
    },
    {
      path: '/login',
      name: 'login',
      component: login
    },
    {
      path: '/mycar',
      name: 'mycar',
      component: mycar,
      meta:{
        needAuth:true
      }
    },
    {
      path: '/mydetail',
      name: 'mydetail',
      component: mydetail
    },
    {
      path: '/myorder',
      name: 'myorder',
      component: myorder
    },
    {
      path: '/myaxios',
      name: 'myaxios',
      component: myaxios
    }
  ]
})

1.1.4 发起get请求


调用接口获取数据并渲染页面。

03myaxios.vue

<template>
  <div>
    <h1>axios</h1>
    <ul>
      <li v-for="(item, i) in list" :key="i">
        <img :src="item.picUrl" alt=""/>
      </li>
    </ul>
  </div>
</template>

<script>
  export default {
    data(){
      return{
        list:[]
      }
    },
    created() {
      this.$axios.get('http://api.mm2018.com:8095/api/goods/home')
      .then(res => {
        console.log(res.data.result[0].contents);
        this.list = res.data.result[0].contents;
      })
    }

  }
</script>

<style scode>

</style>

1.2 配置全局域名

在一个项目中调用数十次接口是很常见的,后期一旦根域名发生改变,所有接口都需要修改,非常繁琐且容易出错。

this.$axios.get方法:

  • 第一个参数是接口地址
  • 第二个参数是包含根域名

axios提供了设置根域名的方法。
在main.js全局入口文件中,设置:axios.default.baseURL = "http://api.mm2018.com:8090"

main.js

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'

// 0、引入通信库axios
import axios from 'axios';
Vue.prototype.$axios = axios;

// 配置全局域名
axios.defaults.baseURL = "http://api.mm2018.com:8090";

// 1、引入Element-ui组件
// import { Button } from 'element-ui';
// Vue.use(Button)

// 2、引入Mint-ui组件
import 'mint-ui/lib/style.css';
import {Button} from 'mint-ui';
Vue.component(Button.name, Button);

Vue.config.productionTip = false  //设置在控制台环境进行代码提示作用

// 1.全局路由守卫
router.beforeEach((to,from,next) => {
  /*
    to:表示要去的新页面
    from:表示旧的页面
    next:表示是否
  */
  // 0——表示未登录
  // 1——表示已登录
  var islogin = 1;
  if(to.meta.needAuth){
    if(islogin == 0){
      router.push({name:'login'})
    }
    if(islogin == 1){
      next()
    }
  }else{
    next()
  }
})


// 2.全局过滤器
Vue.filter('toFixed1',function(val,data,data1){
  return data1 + val.toFixed(data)
})

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  components: { App },
  template: ''
})

组件 03myaxios.vue

<template>
  <div>
    <h1>axios</h1>
    <ul>
      <li v-for="(item, i) in list" :key="i">
        <img :src="item.picUrl" alt=""/>
      </li>
    </ul>
  </div>
</template>

<script>
  export default {
    data(){
      return{
        list:[]
      }
    },
    created() {
      this.$axios.get('/api/goods/home')
      .then(res => {
        console.log(res.data.result[0].contents);
        this.list = res.data.result[0].contents;
      })
    }

  }
</script>

<style scode>

</style>

1.2.1 代码分离

随着接口的增加,created生命周期中的代码会越来越多,不利于后期维护。
可以将代码进行分离,把逻辑代码在methods中封装成一个方法,created只负责调用方法。

<template>
  <div>
    <h1>axios</h1>
    <ul>
      <li v-for="(item, i) in list" :key="i">
        <img :src="item.picUrl" alt=""/>
      </li>
    </ul>
  </div>
</template>

<script>
  export default {
    data(){
      return{
        list:[]
      }
    },
    
    methods:{
      // 1.在methods中声明方法
      getData(){
        this.$axios.get('/api/goods/home')
        .then(res => {
          console.log(res.data.result[0].contents);
          this.list = res.data.result[0].contents;
        })
      }
    },
    
    created() {
      // 2.在created中调用方法
      this.getData();
    }
  }
</script>

<style scode>

</style>

1.3 axios 传递参数

在请求接口的过程中,传递参数是必不可少的。

  • 传参方式1:通过 this.$axios.get() 中的参数params属性
<template>
  <div>
    <h1>axios</h1>
    <ul>
      <li v-for="(item, i) in list" :key="i">
        <img :src="item.picUrl" alt=""/>
      </li>
    </ul>
  </div>
</template>

<script>
  export default {
    data(){
      return{
        list:[]
      }
    },
    methods:{
      // 1.在methods中声明方法
      getData(){
        this.$axios.get('http://api.mm2018.com:8095/api/goods/home')
        .then(res => {
          console.log(res.data.result[0].contents);
          this.list = res.data.result[0].contents;
        })
      },
      getData1(){
        this.$axios
        .get("http://longlink.mm2018.com:8086/selectDemo",{
          params:{
            id:100
          }
        })
        .then(res =>{
          console.log(res);
        });
      },
    },
    created() {
      // 2.在created中调用方法
      this.getData();
      this.getData1();
    }
  }
</script>

<style scode>

</style>
  • 传参方式2:axios提供的通用形式
<template>
  <div>
    <h1>axios</h1>
    <ul>
      <li v-for="(item, i) in list" :key="i">
        <img :src="item.picUrl" alt=""/>
      </li>
    </ul>
  </div>
</template>

<script>
  export default {
    data(){
      return{
        list:[]
      }
    },
    methods:{
      // 1.在methods中声明方法
      getData(){
        this.$axios.get('http://api.mm2018.com:8095/api/goods/home')
        .then(res => {
          console.log(res.data.result[0].contents);
          this.list = res.data.result[0].contents;
        })
      },
      getData1(){
        this.$axios
        .get("http://longlink.mm2018.com:8086/selectDemo",{
          params:{
            id:100
          }
        })
        .then(res =>{
          console.log(res);
        });
      },
      getAll(){
        this.$axios({
          methods:"get",
          url:"http://api.mm2018.com:8095/api/goods/home",
          // data:{} 如果是post请求参数写在data中
          data:{}
        }).then(res =>{
          console.log(res);
        })
      }
    },
    created() {
      // 2.在created中调用方法
      // this.getData();
      // this.getData1();
      this.getAll();
    }
  }
</script>

<style scode>

</style>

1.4 axios原理之promise

axios是基于promise的HTTP库,支持promise的所有API,promise是JS中解决异步编程的语法。

  • 从语法上讲,promise可以看作是一个构造函数
  • 从功能上讲,promise对象用来封装异步操作并获取结果。

1.4.1 什么是promise

promise支持链式调用,可以解决回调地狱。

  • 什么是回调地狱?
    回调地狱涉及多个异步操作,多个回调函数嵌套使用。例如:有3个异步操作,第2个异步操作是以第1个异步操作的结果为条件的,同理第3个异步操作是以第2个异步操作的结果为条件。

1.4.2 为什么使用promise

  • promise支持链式调用,可以解决回调地狱。
  • 回调地狱涉及多个异步操作,多个回调函数嵌套使用。例如有3个异步操作,第2个异步操作是以第1个异步操作的结果为条件的,同理第3个异步操作是以第2个异步操作的结果为条件的。
  • 此时出现了回调函数嵌套,代码将向右侧延伸,不便于阅读,也不便于异常处理,使用promise首先能解决回调函数嵌套问题,代码从上往下执行,更有利于代码阅读及代码异常处理。

1.4.3 promise的基本使用

    myPromise(){
      const p = new Promise((resolve, reject) => {
        // 执行异步操作
        setTimeout(() => {
          const time = Date.now();
          // 当前时间为偶数代表成功,当前时间为奇数代表失败
          if(time % 2 == 0){
            // 执行成功调用resolve(value)
            resolve('成功的数据:' + time)
          } else {
            // 执行失败调用reject(reason)
            reject('失败的数据:' + time)
          }
        }, 1000)
      })

      // 调用异步then
      p.then(
        value => {
          // 成功接收value数据
          console.log('接受成功的数据---' + value);
        },
        reason => {
          // 失败接受reason数据
          console.log('接受失败的数据---' + reason);
        }
      )
    }


代码解析如下:

  • 1、new Promise() 实例对象要传入回调函数,回调函数有两个形参,分别是 resolvereject
  • 2、在回调函数中执行异步操作,在此案例中是获取当前时间,如果当前时间为偶数,表示异步操作执行成功,如果当前时间为奇数,表示异步操作执行失败。
  • 3、如果当前时间为偶数,则调用成功的resolve()方法,方法中的参数就是需要展示的数据。
  • 4、如果当前时间为奇数,则调用失败的reject()方法,方法中的参数就是需要展示的数据。
  • 5、使用 .then() 方法获取成功或失败的数据,如果获取数据成功,则调用第一个回调函数,如果获取数据失败,则调用第二个回调函数。

1.4.4 promise的常用API

1. Promise(excutor){}
  • (1)、excutor()函数:同步执行(resolve, reject) => {}。
  • (2)、resolve()函数:定义成功时调用的函数value => {}。
  • (3)、reject()函数:定义失败时调用的函数reason => {}。

注意:excutor会在promise内部立即同步回调,异步操作则在执行器中执行。

2. Promise.prototype.then()方法:(onResolved,onRejected) => {}

在Promise的原型中存在then()方法,所有的Promise事件都可以调用。
对于是执行成功的回调函数还是执行失败的回调函数,根据Promise函数返回结果判定。

  • (1)、onResolved()函数:成功的回调函数为(value) => {}。
  • (2)、onRejected()函数:失败的回调函数为(reason) => {}。
<script>
	/*
		(1)、excutor()函数:同步执行(resolve, reject) => {}。
		(2)、resolve()函数:定义获取数据成功时调用的函数value => {}。
		(3)、reject()函数:定义获取数据失败时调用的函数reason => {}。
		异步执行是在大括号内执行。
		
		对于是执行成功的回调函数还是执行失败的回调函数,根据Promise函数返回结果判定
	*/
	var p1 = new Promise(resolve, reject) =>{
		setTimeout(() => {
			resolve('获取成功的数据');
			// reject(111);
		},1000)
	}
	
	// 当前的then()方法既可以处理获取成功的数据也可以处理获取失败的数据
	p1.then((value) => {
		console.log("成功==" + value);
	}, (reason) => {
		console.log("失败=="+value);
	});
</script>
3. Promise.prototype.catch()方法:(onRejected) => {}

onRejected()函数:失败的回调函数为(reason) => {}。

<script>
	/*
		(1)、excutor()函数:同步执行(resolve, reject) => {}。
		(2)、resolve()函数:定义获取数据成功时调用的函数value => {}。
		(3)、reject()函数:定义获取数据失败时调用的函数reason => {}。
		异步执行是在大括号内执行。
		
		对于是执行成功的回调函数还是执行失败的回调函数,根据Promise函数返回结果判定
	*/
	var p1 = new Promise(resolve, reject) =>{
	setTimeout(() => {
		// resolve('获取成功的数据');
		reject(111);
	},1000)
	}
	
	// 当前的then()方法既可以处理获取成功的数据也可以处理获取失败的数据
	p1.then((value) => {
	console.log("成功==" + value);
	})
	
	p1.catch(reason => {
	// 获取失败的数据
	console.log(reason);
	})

</script>
4. Promise.resolve()方法:(value) => {}

value:成功的数据。

  • 案例:定义成功值为1的promise对象。
/*
	定义成功回调的数据
*/
var p2 = new Promise((resolve, reject) => {
   resolve(1);
})
p2.then(value => {
	console.log(value);
})

var p2 = Promise.resolve(123);
p2.then(value => {
	console.log(p2);
})
5. Promise.reject()方法:(reason) => {}

reason:失败的原因。

  • 案例:定义失败值为2的promise对象。
/*
	定义失败回调的数据
*/
var p3 = Promise.reject(456);
p3.then(null, reason => {
	console.log(reason);
})
 
// 或
p3.catch(reason => {
	console.log(456);
})
6. Promise.all()方法:(promises) => {}

promises:多个promise数组。

  • 作用:返回一个新的promise对象,当数组中的所有promise对象都执行成功,才为成功,只要数组中有一个promise对象执行失败,就为失败。
<script>
	/*
		Promise数组中只有全部成功获取数据才会成功回调,
		只要有一个失败获取数据就失败回调
	*/
	var p1 = Promise.resolve(1);
	var p2 = Promise.resolve(2);
	var p3 = Promise.resolve(3);
	var p4 = Promise.reject(4);
	
	var pAll = Promise.all(p1,p2,p3);
	pAll.then(values => {
		// 成功调用
		console.log('成功' + values);
	},reason => {
		// 失败调用
		console.log('失败' + reason);
	})
</script>
7.Promise.race()方法:(promises) => {}

promises:多个promise对象的数组。

  • 作用:返回一个新的promise对象。第一个完成promise的状态就是最终的结果状态。
    <script>
		/*	
			Promise.race()获取最先执行的状态
			Promise数组中是同步顺序执行,谁放在最前面谁先执行。
		*/
		var p1 = Promise.resolve(1);
		var p2 = Promise.resolve(2);
		var p3 = Promise.resolve(3);
		var p4 = Promise.reject(4);
		
		var rach = Promise.race([p1,p2,p3,p4]);
		pAll.then(values => {
			// 成功调用
			console.log('成功' + values);
		},reason => {
			// 失败调用
			console.log('失败' + reason);
		})
		
	</script>

1.4.5 async与await

asyncawait 是编写异步操作的解决方案,也是建立在promise基础上的新写法,两者同时使用,如果在方法中使用了await,那么在方法前面加上async。 await必须写在async函数中,但async函数中可以没有await。

<script>
	/*	
		1、async修饰函数的返回值是Promise对象
		2、Promise对象的结果成功或失败由async函数的返回值决定
	*/
	async function f1(){
		return 'hello'
		// return Promise.reject(123);
	}
	var res = f1()
	console.log(res);  // Promise object
	
	// 获取Promise对象中数据
	res.then(value => {
		console.log('成功==' + value);
	}, reason => {
		console.log('失败==' + reason);
	})
</script>
1、async函数

A. async()函数使用
作用:返回promise对象。async的右侧是一个函数,函数的返回值是promise对象。

  • (1) async函数的返回值为promise对象。
  • (2) promise对象的结果,由async函数执行的返回值决定。

async function fn1(){
	return "hello async"
}
const res = fn1()
console.log(res)  // Promise object

如果fn1()函数前面不加async,毫无疑问,res的打印结果应该是hello async,加上async之后将打印promise对象。
既然返回的是promise对象,获取数据就要使用.then方法,并且要设置成功的回调函数和失败的回调函数。

B. then()函数获取成功回调值

async function fn1(){
	return "hello async"
}
const res = fn1()
res.then(
	value => {
		console.log('成功的回调:' + value)
	},
	reason => {
		console.log('-------------' + reason)
	}
)


运行代码,此时在.then中执行的是成功的回调函数。

C. 回调失败返回
加上async之后,返回的是promise对象,我们也可以直接在fn1函数中设置返回失败的数据。

async function fn1(){
	return Promise.reject('失败的数据')
}
const res = fn1()
res.then(
	value => {
		console.log('成功的回调:' + value)
	},
	reason => {
		console.log('-------------' + reason)
	}
)

2、await表达式

作用:等待async函数执行完成,并返回async函数成功的值。

<script>
	/*	
		await作用可以直接获取async函数的值
		await必须要在async函数中
		await只能用于获取成功的数据,不能用于获取失败的数据。可以使用try...catch...来捕捉获取失败的值
	*/
	async function f1(){
		return 'hello';
		// return Promise.reject(123); // await获取会报错
	}
	
	async function f2(){
		try{
			var res = await f1();
			console.log(res);  // hello
		}catch(error){
			console.log(error);
		}
	}
	f2();
</script>
在线咨询 拨打电话

电话

010-67916526

微信二维码

微信二维码