閱讀323 返回首頁    go 阿裏雲 go 技術社區[雲棲]


基於阿裏的Node全棧之路(五)前後端分離進階-接口篇

上一篇文章我就簡單的貼了下代碼,放出來不到一天就破千了,這讓我非常的意外,也很開心;) 我會好好的把上一篇的代碼注釋補一下的。然後決定再放一些我的代碼和理解,俗話說:

Talk is cheap, show me the code!

還記得我的架構中,隻有前端靜態代碼,同時所有的請求是經過跨域發到api上的,那麼這次,我們就來好好的分析下request接口的實現和我自己嚐試的一種的開發流程——api文檔(新接口文檔)


_1_

先貼上我之前的前後端分離的方式,再簡單的介紹下,看過前麵文章的同學直接跳過哈!
看這個圖,我現在對web端的開發,因為是用vue寫的,vue本身會把代碼打包成靜態文件:

  • -static
  • -index.html

這樣意味著,用了vue或者類似框架的時候,我們會拋棄了以前的一個東西叫動態web語言,具體點就是說像asp、jsp等,在客戶訪問前會根據一些條件渲染出對應的網頁出來,而這正是vue這類型的框架要實現的功能,嗯,可以說是衝突了。我當時還會習慣性的部署docker容器來存放這些靜態資源,然後啟動一個node express來監聽接口,但後來仔細想想,這不是像OSS這些要做的事情嗎!? 所以,就有了前麵的兩篇文章:
1. 基於阿裏的Node全棧之路(三)利用阿裏雲OSS實現前後端分離
編輯 刪除

2. 基於阿裏的Node全棧之路(四)前後端分離進階-自動上傳前端代碼到OSS

嗯嗯,這也是我前後端分離的第一步。

好,上麵都是重新溫故下我之前的文章,因為我發現看我前麵幾篇文章好像並沒有想象中的那麼容易閱讀,所以再次重溫一遍。

敲黑板!敲黑板!

這次,我分享的是我對api請求接口的封裝,可能很多同學會說,這有什麼難的,要用請求的時候,調用一下ajax什麼的就可以了。emmm..., 是可以的,不過那樣的代碼對於非常追求代碼美感的我來說,是灰常難忍受的!

既然我們是前後端分離,那麼我們應該規對接的接口的結構,對吧?我在項目中,強製規定所有的api都應該長這樣

const api_host = `https://api.${你的域名}\${你的項目名\${api_version}`;//https://api.xxxxx.com/blog/v1
//api遵循restful設計,這裏規定api返回結構
const response = {
  code:Number,
  /*
   * 小於0是錯誤,這裏前端不需要關心錯誤是什麼,
   * 等於0是沒有權限
   * 大於0表示成功
   * 我這麼設計是由原因的,歡迎大家來一起探討
   */
  msg:String,//當然,你也可以叫errMsg,message什麼的,隨便你啦
  /*
   * 在我這裏,默認隻有錯誤的時候,才會出現
   */
  data:Object,
  /* 
   * 後端返回對象,我們一直說前後端語言一樣,有很多好處,呐,這裏就是!
   * 這樣寫,基本能保證後端傳給前端是什麼,前端收到的就是什麼
   */
};

下麵放上我的代碼,然後我再詳細解析下:

/* eslint-disable */
import axios from 'axios';

const MyPlugin = {};
axios.defaults.withCredentials = true;//唯有加上這句話,才能夠支持跨域請求,如果實在不明白的可以留言

MyPlugin.install = function install(Vue, api_host) {
  //構建axios請求基礎
  const request = axios.create({
    baseURL: api_host,//api host:顧名思義就是api的請求基礎地質
    timeout: 30000// 超時時間
  });
  //請求方法的構建,type為:get、post、delete等等
  const createRequestFuc = (type) => {
    return function (resource, params, showError = true) {
      //返回請求的Promise的對象
      return new Promise((resolve, reject) => {
        this.$Loading.start();//請求發起時,show loading,一般的框架都會有全局調用的loading方法。
        params = type === 'get' ? { params } : params;//axios裏get方法和其它方法接收參數的方式不一致,這裏做個統一
        request[type](resource, params)//調用request
          .then(res => {
            if (res && res.data && res.data.code > 0) {//判斷請求返回結果,code為判斷值,這裏可以替換成你自己的框架定義
              resolve(res.data.data);//返回結果
            } else {
              showError && this.$Message.error(res.data.msg);//判斷是否調用自帶全局waring或error
              reject(res.data.msg);//無論上麵是否執行,都應該reject,阻止代碼繼續執行
            }
            this.$Loading.finish();//結束loading
          })
          .catch((err) => {
            this.$Message.error('請求失敗!');//這種情況一般是請求失敗,報錯方式可以自己更改
            this.$Loading.finish();//結束loading
            reject(err);//無論上麵是否執行,都應該reject,阻止代碼繼續執行
          });
          //特別注意:vue install方式安裝的插件,this就是vue component對象。
      });
    }
  }
  //構建請求
  Vue.prototype.$get = createRequestFuc('get');
  Vue.prototype.$put = createRequestFuc('put');
  Vue.prototype.$post = createRequestFuc('post');
  Vue.prototype.$patch = createRequestFuc('patch');
  Vue.prototype.$delete = createRequestFuc('delete');
};
export default MyPlugin;
/* eslint-enable */

這是一個我寫的插件,上篇文章講到vuexiang項目用webpack模板構建對吧,那麼你現在寫前端xia項目應該都是以".vue"結尾的文件,那麼你隻需要在main.js裏麵把它引用進來就可以了:

import Vue from 'vue';
import Request from '@/plugins/request';


Vue.use(Vuex);
Vue.use(Request,'https://api.xxxxx.com/v1');//這裏

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

好,到這裏估計寫過vue的老鳥都已經明白了,沒搞懂的童鞋嘞,那就繼續看下去吧!
接下來,你隻需要在vue文件裏麵直接使用就行了,這裏再貼一份簡單登錄代碼給大家參考:

<template>
  <div >
    <Input type="text" v-model="user_form.username" placeholder="phone">
    <Input type="password" v-model="user_form.password" placeholder="phone">
    <Button type="primary" @click="login">Log in</Button>
  </div>
</template>
<script>

export default {
  async created() {
    const session = await this.$get('session', {}, false);
    this.setSession(session);
  },
  data() {
    return {
      user_form: {
        phone: '',
        password: '',
      },
    };
  },
  methods: {
    async login() {
      const session = await this.$post('session', this.user_form);
      this.setSession(session);
    },
    setSession(session) {
      //這裏放置像vuex這些,存放session的fangfa,當然!你也可以用vuex的mapMutations,我就是這麼做的^.^
    },
  },
};
</script>

嘿嘿,上麵的代碼簡單不。當然,你要喜歡promise回調或者yield都一樣的,隨便你,我這裏隻是想分享一種思想,因為這種方式,是可以在node裏麵得到廣泛應用的,為了證明這點,我再貼一份我的react-native版本的request接口:

/* eslint-disable */
import axios from 'axios';
import { ShowWarnMsg } from './toast';
const api_host = 'https://api.xxxxxx.com/project_name/v1';

//構建axios請求基礎
const request = axios.create({
  baseURL: api_host,//api host:顧名思義就是api的請求基礎地質
  timeout: 30000// 超時時間
});
//請求方法的構建,type為:get、post、delete等等
const createRequestFuc = (type) => {
  return function (resource, params, showError = true) {
    //返回請求的Promise的對象
    return new Promise((resolve, reject) => {
      params = type === 'get' ? { params } : params;//axios裏get方法和其它方法接收參數的方式不一致,這裏做個統一
      request[type](resource, params)//調用request
        .then(res => {
          if (res && res.data && res.data.code > 0) {//判斷請求返回結果,code為判斷值,這裏可以替換成你自己的框架定義
            resolve(res.data.data);//返回結果
          } else {
            showError && ShowWarnMsg(res.data.msg);//判斷是否調用自帶全局waring或error
            reject(res.data.msg);//無論上麵是否執行,都應該reject,阻止代碼繼續執行
          }
        })
        .catch((err) => {
          ShowWarnMsg('請求失敗!');//這種情況一般是請求失敗,報錯方式可以自己更改
          reject(err);//無論上麵是否執行,都應該reject,阻止代碼繼續執行
        });
      //特別注意:vue install方式安裝的插件,this就是vue component對象。
    });
  }
};
export const $get = createRequestFuc('get');
export const $put = createRequestFuc('put');
export const $post = createRequestFuc('post');
export const $patch = createRequestFuc('patch');
export const $delete = createRequestFuc('');

global.HTTP = {
  $get,
  $put,
  $post,
  $patch,
  $delete,
};

export default global.HTTP;
/* eslint-enable */

區別不大吧,別學我用global,我隻是偷懶。

最後更新:2017-09-27 14:04:21

  上一篇:go  2017年杭州雲棲大會容器技術專場我們不見不散~
  下一篇:go  阿裏雲MaxCompute澳大利亞開服,“領跑”人工智能市場