# 解构前端登录请求

## 封装request API

> 文中@一律代表 src目录

首先对请求地址进行封装，将请求与页面解构。在`@/api/user.js`中封装了与用户登录，信息查找等相关的前端请求

```javascript
import request from '@/utils/request'

export function login(data) {
  return request({
    url: '/login',
    method: 'post',
    data,  //发生给后端的数据，没有就填null
  })
}
```

## vuex进行状态管理

在vuex中封装一个与user操作有关的状态，

```javascript
const getDefaultState = () => {
  return {
    token: getToken(), //状态，用于判断当前是否已经登录
    username: '',
  }
}
const state = getDefaultState()

const mutations = {
  RESET_STATE: (state) => {
    Object.assign(state, getDefaultState())
  },
  SET_TOKEN: (state, token) => {
    state.token = token  //设置当前状态
  },
}
```

## 登录的异步操作

在html页面中启动异步操作，

* `loginForm`是登录组件的一个表单
* 使用`dispatch`启动异步的vuex任务，这里`action`的名字取决于`namespaced`
* 由于是登录操作，异步请求后不会得到数据，有数据也被放在vuex里了，因此`then`之后可以进行其他操作

```javascript
      this.$store
        .dispatch("user/login", {
          username: this.loginForm.username,
          password: cryptPW(this.loginForm.password),
        }) //加盐
        .then(() => {
          alert("登录成功");
        })
        .catch(() => {
          alert("登录失败");
        });
```

这里只注册了一个`login`的操作，当进行login操作的时候，返回一个`promise`对象，promise对象中调用`@/api/user.js`中的`login`请求；后台响应的数据首先在`@/utils/request.js`中会被拦截，如果请求没有出错的话将会返回一个response的Promise，否则返回一个Error的Promise

* 正常响应的数据在`then`方法中被捕获到，根据响应的数据提交`commit`设置vuex的状态，同时调用`setToken`设置cookie；最后将响应数据交给页面
* 异常的响应或者自定义的错误，由于Promise的链传递性最终将会被`catch`捕获

```javascript
const actions = {
  login({ commit }, userInfo) {
    const { username, password } = userInfo
    return new Promise((resolve, reject) => {
      login({ username: username.trim(), password: password })
        .then((reponse) => {
          const { token } = reponse.data
          commit('SET_TOKEN', token)
          setToken(token)
          resolve(reponse)
        })
        .catch((err) => {
          reject(err)
        })
    })
  },
}
```

## 响应拦截

* 正常响应代码为0
* 当响应出错时，返回一个`reject`，并且reject中是一个Error对象

```javascript
function handleReponse(response) {
  if (response.data && parseInt(response.data.code) === 0) {
    return response.data
  } else {
    switch (parseInt(response.data.code)) {
      case 0:
        break
      case 404:
        Notification.error({
          title: 'error',
          message: '后端接口网址未找到, 错误代码404',
          duration: 5000,
        })
        break
      default:
        Notification.error({
          title: 'error',
          message: '未知错误，错误代码:' + response.data.code,
          duration: 5000,
        })
    }
    return Promise.reject(
      new Error(
        response.data.code ? 'error code:' + response.data.code : 'Error'
      )
    )
  }
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://zpliu.gitbook.io/booknote/vuex/deng-lu.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
