Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vue中axios和await/async的使用 #16

Open
Wscats opened this issue Jul 18, 2017 · 0 comments
Open

vue中axios和await/async的使用 #16

Wscats opened this issue Jul 18, 2017 · 0 comments

Comments

@Wscats
Copy link
Owner

Wscats commented Jul 18, 2017

安装

安装或者引入CDN文件

npm install axios
<script src="https://unpkg.com/axios/dist/axios.js"></script>
<!--<script src="https://unpkg.com/axios/dist/axios.min.js"></script>-->

GET

在Vue原型链上绑定,就可以全局使用$http方法

import axios from 'axios';
Vue.prototype.$http = axios;

然后我们就可以,其他地方使用的话,如同使用vue-resource一样,我们还可以在get或者post请求后面增加请求头header

this.$http.get("http://www.tuling123.com/openapi/api", {
    params: {
        key: "c75ba576f50ddaa5fd2a87615d144ecf",
        info: "先有鸡还是先有蛋"
    },
    header:{}
}).then((data) => {
    console.log(data);
    //success callback
}, (err) => {
    //error callback
})

POST

post请求比get请求复杂一点,首先降Content-Type格式为application/x-www-form-urlencoded,因为axiospost方法默认使用application/json格式编码数据,那么解决方案就有两种,一是后台改变接收参数的方法,另一种则是将axiospost方法的编码格式修改为application/x-www-form-urlencoded,这样就不需要后台做什么修改了

import axios from 'axios'
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';//全局更改
import qs from "qs";//配合qs模块转化post请求的参数,记得先npm install qs
Vue.prototype.$axios = axios;
Vue.prototype.$qs = qs;

然后在组件中这样使用

export default {
    this.$axios({
      method: "post",
      //headers: { "content-type": "application/x-www-form-urlencoded" },//局部更改
      url: "http://localhost:3000/users/test",
      data: this.$qs.stringify({
        name: ""
      })
    }).then(res => {
      console.log(res);
    });
  }
};

具体或者其他方法可以参考官方文档的这篇解决方案using-applicationx-www-form-urlencoded-format

代理

比如在vue-cli3中我们可以这样配置代理来解决跨域问题,在package.jsonbabel.config.js同级目录下新建vue.config.js文件写入以下代码

module.exports = {
    baseUrl: '/',
    devServer: {
        proxy: {
            '/api': {
                target: 'https://m.nubia.com',
                changeOrigin: true,
                ws: true,
                pathRewrite: {
                  '^/api': ''
                }
            }
        }
    }
}

正常情况请求https://m.nubia.com/show/page/phoneType是会跨域的,经过上面配置,就可以用/api/show/page/phoneType代替来访问

this.$axios({
    method: "get",
    url: "/api/show/page/phoneType",
    //    /api/show/page/phoneType代替https://m.nubia.com/show/page/phoneType
}).then(res => {
    console.log(res);
});

二次封装

我们可以对 axios 进行一次二次封装,方便我们做全局的请求拦截或者全局的加载动画,这里我们也需要引入 qs 模块对 post请求的参数进行处理,并且把它命名为 http.js,可以在其他组件引入使用

import axios from 'axios'
import qs from 'qs'

axios.interceptors.request.use(config => {
    // loading 做loading的加载动画
    return config
}, error => {
    return Promise.reject(error)
})

axios.interceptors.response.use(response => {
    return response
}, error => {
    return Promise.resolve(error.response)
})

function checkStatus(response) {
    // loading
    // 如果http状态码正常,则直接返回数据
    if (response && (response.status === 200 || response.status === 304 || response.status === 400)) {

        return response
        // 如果不需要除了data之外的数据,可以直接 return response.data
    }
    // 异常状态下,把错误信息返回去
    return {
        status: -404,
        msg: '网络异常'
    }
}

function checkCode(res) {
    // 如果code异常(这里已经包括网络错误,服务器错误,后端抛出的错误),可以弹出一个错误提示,告诉用户
    if (res.status === -404) {
        alert(res.msg)
    }
    if (res.data && (!res.data.success)) {
        alert(res.data.error_msg)
    }
    return res
}

export default {
    post(data, url) {
        return axios({
            method: 'post',
            url: url,
            data: qs.stringify(data),
            timeout: 10000,
            headers: {
                'X-Requested-With': 'XMLHttpRequest',
                'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
            }
        }).then(
            (response) => {
                return checkStatus(response)
            }
        )
    },
    get(url, params) {
        return axios({
            method: 'get',
            baseURL: 'https://cnodejs.org/api/v1',
            url,
            params, // get 请求时带的参数
            timeout: 10000,
            headers: {
                'X-Requested-With': 'XMLHttpRequest'
            }
        }).then(
            (response) => {
                return checkStatus(response)
            }
        ).then(
            (res) => {
                return checkCode(res)
            }
        )
    }
}

安装async和await支持

webpack自己搭建的脚手架即使按照官网安装好最新的babel,它本身也还是不支持async/await

所有还需要额外安装

npm install --save-dev babel-plugin-transform-runtime
npm install --save babel-runtime // `babel-plugin-transform-runtime` 插件本身其实是依赖于 `babel-runtime` 的,但为了适应 `npm install --production` 强烈建议添加该依赖。

webpack文件夹目录新增一个. babelrc,这份是babel配置文件

然后在里面写入

{
  "plugins": ["transform-runtime", "babel-plugin-transform-regenerator", "babel-plugin-transform-es2015-modules-commonjs"]
}

webpackuse里面的options注释掉

{
    test: /\.js$/,
    // 除了node_modules|bower_components所有的js文件都用babel-loader处理
    exclude: /(node_modules|bower_components)/,
    use: {
        loader: 'babel-loader',
        // options: {
        //     presets: ['@babel/preset-env']
        // }
    }
}

配合awiat和async

引入上面的 http.js 然后在 methods 属性里面定义一个 getData 方法并用 async 关键词,测试发现不加也没有问题,然后就可以在里面对每一个异步请求返回的 promise 请求进行 await 同步队列处理,这样就可以解决很多在 vue 中经常出现的问题,比如回调嵌套或者 this 的指向性问题

关于promise&&await&&deferred和event loop可以参考这里

import http from "../libs/http.js";
export default {
  data() {
    return {
      topics: null,
      topic: null
    };
  },
  methods: {
    async getData() {
      // 两个异步请求变为同步执行,也不需要再
      // 执行顺序是 topics -> -----------(2秒后)  -> topic
      // topics异步
      const topics = await http.get("https://cnodejs.org/api/v1/topics", {
        page: 1,
        tab: "ask",
        limit: 10,
        mdrender: false
      });
      console.log("topics");
      this.topics = topics.data.data;
      // setTimeout异步
      const test = await (() => {
        return new Promise((resolve, reject) => {
          setTimeout(() => {
            resolve("-----------");
          }, 2000);
        });
      })();
      console.log(test);
      // topic异步
      const topic = await http.get(
        "https://cnodejs.org/api/v1/topic/5433d5e4e737cbe96dcef312"
      );
      console.log("topic");
      this.topic = topics.data.data;
    }
  },
  mounted() {
    this.getData();
  }
};

参考文档

@Wscats Wscats changed the title vue axios vue的axios使用 Oct 23, 2018
@Wscats Wscats changed the title vue的axios使用 vue中axios和await/async的使用 Jan 17, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant