7.接口封装

113 阅读2分钟

Promise

什么是 Promise

Promise 是一个对象,对象里存储一个状态,这个状态是可以随着内部的执行转化的,为以下三种状态之一:等待态(Pending)、完成态(Fulfilled)、拒绝态(Rejected)。

一开始,我们先设置好等状态从 pending 变成 fulfilled 和 rejected 的预案(当成功后我们做什么,失败时我们做什么)。

Promise 启动之后,当满足成功的条件时我们让状态从 pending 变成 fullfilled (执行 resolve);当满足失败的条件,我们让状态从 pending 变成 rejected(执行 reject)

Promise 的用法

一个getip()
getCityFromIp(ip) 通过ip获取城市的名字
getWeatherFromCity(city) 通过城市的名字获取城市的天气

之前只能用回调,

Promise.prototype.then / Promise.prototype.catch

Promise.all


var p1 = getCityFromIp('10.10.10.1')
var p2 = getCityFromIp('10.10.10.2')
var p3 = getCityFromIp('10.10.10.3')

//Promise.all, 当所有的 Promise 对象都完成后再执行
Promise.race([p1, p2, p3]).then(data=>{
  console.log(data)
})

Promise.race

对于开头回调地狱的解决

样式

function fn(){
	return new Promise((resolve,reject)=>{
	成功时调用resolve()
	失败时调用reject()
 })
}

fn().then(success,fail).then(success2,fail2)

解决

function fn1() {
  return new Promise((resolve, reject)=>{
    setTimeout(()=>{
      console.log('fn1...')
      resolve()
    }, 1000)    
  })
}

function fn2() {
  return new Promise((resolve, reject)=>{
    setTimeout(()=>{
      console.log('fn2...')
      resolve()
    }, 1000)    
  })
}

function fn3() {
  return new Promise((resolve, reject)=>{
    setTimeout(()=>{
      console.log('fn3...')
      resolve()
    }, 1000)    
  })
}

function onerror() {
  console.log('error')
}

fn1().then(fn2).then(fn3).catch(onerror)

引入axois,使用Promise进行封装成统一接口

axois 来源于axois的文档


 // `validateStatus` defines whether to resolve or reject the promise for a given
  // HTTP response status code. If `validateStatus` returns `true` (or is set to `null`
  // or `undefined`), the promise will be resolved; otherwise, the promise will be
  // rejected.
  validateStatus: function (status) {
    return status >= 200 && status < 300; // default
  },

实战:

//request.js
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'
axios.defaults.baseURL = baseURLConfig.baseURL
axios.defaults.withCredentials = true

export default function request(url, type = 'GET', data = {}) {
    return new Promise((resolve, reject) => {
        let option = {
            url,
            method: type,
            validateStatus(status) {
                return (status >= 200 && status < 300) || status === 400
            }
        }
        if (type.toLowerCase() === 'get') {
            option.params = data
        } else {
            option.data = data
        }
        axios(option).then(res => {
            if (res.status === 200) {
                resolve(res.data)
            } else {
                console.error(res.data)
                reject(res.data)
            }
        }).catch(err => {
            console.error({ msg: '网络异常' })
            reject({ msg: '网络异常' })
        })
    })
}

Login 组件使用 Auth接口

//Login.vue
import request from "@/helpers/request";

request("/auth/login", "POST", { username: "hunger", password: "123456" }).then(
  (data) => {
    console.log(data);
  }
);
//Sidebar.vue
<script>
import request from "@/helpers/request";
export default {
  components: {
    avatar,
  },
  methods: {
    logout() {
      console.log("logout");
      request("/auth/logout").then((data) => {
        console.log(data);
      });
    },
  },
};
</script>
      request("/auth/register", "POST", {
        username: this.register.name,
        password: this.register.password,
      }).then((data) => {
        console.log(data);
      });
      request("/auth/login", "POST", {
        username: this.login.name,
        password: this.login.password,
      }).then((data) => {
        console.log(data);
      });

解决跨域问题

//request.js
  withCredentials: true, //允许跨域请求

接口封装成API

//auto.js
//统一在这里封装接口成函数

const URL = {
    REGISTER: '/auth/register',
    LOGIN: '/auth/login',
    LOGOUT: '/auth/logout',
    GET_INFO: '/auth'
}

export default {
    register({ username, password }) {
        return request(URL.REGISTER, 'POST', { username, password })
    },

    login({ username, password }) {
        return request(URL.LOGIN, 'POST', { username, password })
    },

    logout() {
        return request(URL.LOGOUT)
    },

    getInfo() {
        return request(URL.GET_INFO)
    }
}
  Auth.login({
        username: this.login.name,
        password: this.login.password,
      }).then((data) => {
        console.log(data);
      });

生产环境和开发环境baseURL 无缝切换

在build下配置mock.config.js 和webpack.dev.conf.js

1.定义两个变量mockBaseURL和realBaseURL,并设置isDev默认为true\
2.,mockBaseURL中isDev为true,realBaseURL中isDev为false\
3.webpack.dev.config.js文件中添加require('./mock.config').config({isDev:true})\
4.webpack.prod.config.js文件中添加require('./mock.config').config({isDev:false})\
5.在开发环境时调用mockBaseURL\
6.在生成环境时调用realBaseURL