您当前的位置: 首页 >  网络

搭建前端网络请求模块

蔚1 发布时间:2020-01-07 23:30:53 ,浏览量:4

  1. HTTP 超文本传输协议
  2. 发送一个请求查询用户日志记录
    • 请求
    • 响应
    • 请求方式有哪些?
    • 响应码有哪些?
    • 客户端请求后,服务器响应携带的 https 证书
    • 常用加密算法
  3. 快速搭建 Vue 普通 H5 项目页面的网络请求
    • JS 变量修饰符
    • 函数 Function
    • Object 对象
    • 对象的定义
    • Ajax 请求
    • Axios 框架
  4. Vue Cli 脚手架项目请求模块的搭建
    • 基础安装环境
    • package.json 配置
    • 配置 main.js
    • 请求 Demo 示例
    • 模块之间的引用和导出
  5. H5 和 App 原生交互
HTTP 超文本传输协议 TCP 三次握手
  1. 客户端发 syn 询问给服务器。
  2. 服务器回应询问 syn,并发送一个指令 ack 客户端。
  3. 客户端回 ack 服务器。 正式连接成功后开始客户端请求 Http 报文,服务器响应报文。三次握手
四次挥手过程

四次挥手

发送一个请求查询用户日志记录 请求
:method: POST:scheme: https:authority: vendor-api-prod.gaoying.com:path: /customer/logs/Accept: application/json, text/plain, */*Content-Type: application/x-www-form-urlencoded  //表单提交方式Origin: http://h5-vendor-dev.gaoying.comContent-Length: 236Accept-Language: zh-cnHost: vendor-api-dev.gaoying.comUser-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148Referer: http://h5-vendor-dev.gaoying.com/page/customerMain.html?customerId=172821&userId=15243265&token=41cadcb70eed35378a92379871a51181Accept-Encoding: gzip, deflate, brConnection: keep-alive
响应
   status: 200   Access-Control-Allow-Origin: *   Content-Type: application/json;charset=UTF-8  //json 响应格式   Date: Fri, 27 Dec 2019 05:58:18 GMT   Server: Tengine
请求方式有哪些?
   METHODS: [      'ACL',         'BIND',       'CHECKOUT',      'CONNECT',     'COPY',       'DELETE',      'GET',         'HEAD',       'LINK',      'LOCK',        'M-SEARCH',   'MERGE',      'MKACTIVITY',  'MKCALENDAR', 'MKCOL',      'MOVE',        'NOTIFY',     'OPTIONS',      'PATCH',       'POST',       'PROPFIND',      'PROPPATCH',   'PURGE',      'PUT',      'REBIND',      'REPORT',     'SEARCH',      'SOURCE',      'SUBSCRIBE',  'TRACE',      'UNBIND',      'UNLINK',     'UNLOCK',      'UNSUBSCRIBE'    ]
响应码有哪些?
STATUS_CODES: {  '100': 'Continue',  '101': 'Switching Protocols',  '102': 'Processing',  '103': 'Early Hints',  '200': 'OK',  '201': 'Created',  '202': 'Accepted',  '203': 'Non-Authoritative Information',  '204': 'No Content',  '205': 'Reset Content',  '206': 'Partial Content',  '207': 'Multi-Status',  '208': 'Already Reported',  '226': 'IM Used',  '300': 'Multiple Choices',  '301': 'Moved Permanently',  '302': 'Found',  '303': 'See Other',  '304': 'Not Modified',  '305': 'Use Proxy',  '307': 'Temporary Redirect',  '308': 'Permanent Redirect',  '400': 'Bad Request',  '401': 'Unauthorized',  '402': 'Payment Required',  '403': 'Forbidden',  '404': 'Not Found',  '405': 'Method Not Allowed',  '406': 'Not Acceptable',  '407': 'Proxy Authentication Required',  '408': 'Request Timeout',  '409': 'Conflict',  '410': 'Gone',  '411': 'Length Required',  '412': 'Precondition Failed',  '413': 'Payload Too Large',  '414': 'URI Too Long',  '415': 'Unsupported Media Type',  '416': 'Range Not Satisfiable',  '417': 'Expectation Failed',  '418': "I'm a Teapot",  '421': 'Misdirected Request',  '422': 'Unprocessable Entity',  '423': 'Locked',  '424': 'Failed Dependency',  '425': 'Unordered Collection',  '426': 'Upgrade Required',  '428': 'Precondition Required',  '429': 'Too Many Requests',  '431': 'Request Header Fields Too Large',  '451': 'Unavailable For Legal Reasons',  '500': 'Internal Server Error',  '501': 'Not Implemented',  '502': 'Bad Gateway',  '503': 'Service Unavailable',  '504': 'Gateway Timeout',  '505': 'HTTP Version Not Supported',  '506': 'Variant Also Negotiates',  '507': 'Insufficient Storage',  '508': 'Loop Detected',  '509': 'Bandwidth Limit Exceeded',  '510': 'Not Extended',  '511': 'Network Authentication Required'}
客户端请求后,服务器响应携带的 https 证书

HTTPS在 HTTP 与 TCP 之间加入 SSL 层,一个加密/身份验证层,用于安全的 HTTP 数据传输。 它是一个 URI scheme(抽象标识符体系)。SSL 是安全套接层 。它的任务是负责在网络传输层基础上对网络连接进行数据加密。具有校验机制,配备身份证书。客户端利用公钥对数据加密,服务端收到加密数据后 对数据进行解密。

https 证书

Https 服务器端口是 443, Https 公共密钥采用 RSA 算法加密,证书信息将在请求响应之前回复给客户端。客户端根据证书信息本地做一个安全校验,通过后再允许服务端响应返回数据,否则取消本次请求响应。签名算法:SHA-256 ECDSA

常用加密算法 对称加密
  • 单向散列函数MD5 是一种不可逆的信息摘要算法,严格来说不是加密。单向散列函数是一种不可逆的信息摘要算法,无法通过密文还原成明文(注意:是算法上不能实现),对于简单的 MD5 加密(这里的简单是指:明文长度短,且字符单一,并且进行 HASH 操作的时候没有进行加盐处理),是可以通过一些在线工具网站解密出来,实则是利用了彩虹表的技术。
  • AES 加密 加密原理:字节代换、行位移、列混合(矩阵相乘:状态矩阵 和 固定矩阵相乘) 、轮钥加密:轮钥加密是将 128 位轮密钥 Ki 同状态矩阵中的数据进行逐位异或操作。
  • DES 加密
非对称加密
  • RSA 加密图片
快速搭建 Vue 普通 h5 项目页面的网络请求

在学习请求之前,需要掌握好 Javascript 语言。最基础的知识首先要了解和掌握变量修饰符,Function 和 Object 对象。

js 变量修饰符

let 是局部变量,非常适合循环的时候。const 是只读变量, 初始化的时候就要赋值,且只能赋值一次。var 是全局变量,全局都可以用。

函数 Function

javascript_function 从上图我们看到有个名为 open 的函数,包含参数、调用者、长度、名字、以及 Proto 对象。该对象里面有 apply 、bind、 call 函数。还有一个 contructor 构造器。

  • Function 属性: length、name、prototype。

  • Function.prototype.apply() //调用一个函数并将其设置为提供的值。 可以将参数作为 Array 对象传递

  • Function.prototype.bind() //创建一个新函数,该新函数在调用时将其设置为提供的值,并在调用新函数时在提供的任何参数之前添加给定的参数序列。

  • Function.prototype.call() //调用一个函数并将其设置为提供的值。 可以按原样传递参数。

  • Function.prototype.toString() //返回表示函数源代码的字符串。

    //题外话,apply 和 bind 增强代码的扩展性,类似 iOS 的 category;

  1. 动态改变 this 的指向,也就是 this 从 callObject 动态切换为 thisArg。

  2. callObject.method.apply(thisArg,thisArray),可以将 thisArray 转化为 arguments,传入到 callObject.method 内部。

    我们通过以下代码来测试 bind 的用法:

//程序员的黄金年龄 18 ~ 35var checkProgramerAgeRange = function (value) {   if (typeof value !== 'number')       return false;   else       return value >= this.minimum && value  {    console.log("step1:异步请求处理耗时任务");    setTimeout(() => {        resolve("qiu");    }, 1000);}).then(value => {    //第一个接口请求成功拿到 qiu    console.log("step1-result:" + value);    return new Promise(resolve => {        console.log("step2-1:异步请求处理耗时任务 2");        setTimeout(() => {            resolve("qiugao");        }, 1000);        //触发第二个接口请求    }).then(value => {        //第二个接口请求成功,拿到 id2 做第一件事情。        console.log("step2-1-result-event1:" + value);        return "qiugaoying";    }).then(value => {        //第二个接口请求成功,拿到 id2 做第二件事情。        console.log("step2-1-result-event2:" + value);        return "hello, my name is qiugaoying";    });}).then(value => {    //最后全部请求完成,触发汇总刷新。    console.log("step1-result:" + value);});/*console 输出结果:step1:异步请求处理耗时任务step1-result:qiustep2-1:异步请求处理耗时任务 2step2-1-result-event1:qiugaostep2-1-result-event2:qiugaoyingstep1-result:hello, my name is qiugaoying*///Promise then 嵌套,方式二: 把 then 移到同一级展开。执行打印结果是一样的。new Promise(resolve => {    console.log("step1:异步请求处理耗时任务");    setTimeout(() => {        resolve("qiu");    }, 1000);}).then(value => {    //第一个接口请求成功拿到 qiu    console.log("step1-result:" + value);    return new Promise(resolve => {        console.log("step2-1:异步请求处理耗时任务");        setTimeout(() => {            resolve("qiugao");        }, 1000);        //触发第二个接口请求    });}).then(value => {    //第二个接口请求成功,拿到 id2 做第一件事情。    console.log("step2-1-result-event1:" + value);    return "qiugaoying";}).then(value => {    //第二个接口请求成功,拿到 id2 做第二件事情。    console.log("step2-1-result-event2:" + value);    return "hello, my name is qiugaoying";}).then(value => {    //最后全部请求完成,触发汇总刷新。    console.log("step1-result:" + value);});
  • then 方法提供两个参数,第二个参数可选。一个是名为 resolve 的成功回调 和 另一个名为 reject 的失败回调。通常处理一个失败回调我们会用 catch 方法去捕捉异常和失败。
    new Promise(resolve => {        console.log("step1:异步请求处理耗时任务");        setTimeout(() => {            resolve("qiu");        }, 1000);    }).then(value => {        //第一个接口请求成功拿到 qiu        console.log("step1-result:" + value);        return new Promise(resolve => {            console.log("step2-1:异步请求处理耗时任务");            setTimeout(() => {                resolve("qiugao");            }, 1000);            //触发第二个接口请求        });    }).then(value => {        //第二个接口请求成功,拿到 id2 做第一件事情。        let hasError = true        if (hasError) {            throw new Error("step2-1-result-event1-error 报异常");            //抛出异常 将不再继续执行 then, 直接到 catch 异常;中途如果没有遇到 catch 将直接到最后的 catch.        } else {            console.log("step2-1-result-event1:" + value);            return "qiugaoying";        }    })    /*.catch(err => {        console.log("中途 catchError 会继续往下走:" + err);        return "qiugaoying"        //也会返回一个 promise 实例,并且是 resolved 状态,不会被最后一个 catch 捕捉    })*/    .then(value => {        //第二个接口请求成功,拿到 id2 做第二件事情。        console.log("step2-1-result-event2:" + value);        return "hello, my name is "+value;    }).then(value => {        //最后全部请求完成,触发汇总刷新。        console.log("step1-result:" + value);    }).catch(error => {        console.log("end error:" + error);    });
  • finally 方法是最终执行的方法(无参),无论状态是什么,成功 or 失败 都会执行收尾。
  • Promise 还提供 all 方法(接收一个数组,里面值可以是普通函数,或者 Promise 对象),可用来做一个类似批量处理之后汇总的业务。
 testPromiseAll() {    function washFood(){        console.log('做饭第一步:洗菜');        let hasError = false;        if(hasError){            return "发现了一只虫子!洗掉它。";        }else{            return '菜洗干净了。';        }    }    function cutFood() {        console.log('做饭第二步:切菜');        var p = new Promise(function (resolve, reject) { //做一些异步操作            setTimeout(function () {                let cutFoodHasError = true;  //控制默契切菜时 是否发生异常                if(cutFoodHasError){                    reject("呜呜~ 割到手了,流血!")                }else{                    resolve('切好了菜。');                }            }, 1000);        })        /* 试试打开这里的注释        .catch(error=>{            console.log("切菜异常:"+error); //异常本身就是返回 resolve 状态,值是 null            console.log("用创口贴止血,继续做菜。");        });        */        return p;    }    function cooking() {        console.log('做饭第三步:炒菜');        var p = new Promise(function (resolve, reject) { //做一些异步操作            setTimeout(function () {                resolve('菜已做好!');            }, 2000);        });        return p;    }    //数组里,如果放 Promise 一定要返回状态。     Promise.all([washFood(), cutFood(),cooking()])        .then((result) => {            console.log('上桌,吃饭了:'+result);            console.log(result);        }).catch(error=>{            console.log("菜没做成,出现了小事故:"+error);        })   /*     结果:     1. 当 cutFoodHasError = true;打印如下结果:        菜没做成,出现了小事故:呜呜~ 割到手了,流血!     2. 当 cutFoodHasError = true 且 cutFood 方法里的 Promise 有异常捕捉时:         切菜异常:呜呜~ 割到手了,流血!        上桌,吃饭了:菜洗干净了!,,菜已做好     3. 当 cutFoodHasError = false         上桌,吃饭了:菜洗好了。切好了菜。菜已做好!    */    /*     Promise.all 使用总结:    数组里可以是 Promise 对象,也可以是别的值,只有 Promise 会等待状态改变    当所有的子 Promise 都完成,该 Promise 完成,返回值是全部值得数组    有任何一个失败,该 Promise 失败,返回值是第一个先失败的子 Promise 结果     */},
  • Promise 另外一个 race 方法。与 all 不同的是:race 类似竞赛,参数中的 Promise 实例只要有一个率先改变状态就会触发结果。
//打印结果: 兔子赢了testPromiseRace() {    function rabbit() {        console.log('兔子选手');        var p = new Promise(function (resolve, reject) {            setTimeout(function () {                resolve('兔子赢了');            }, 1000);        }) .catch(error=>{            console.log("兔子跑步中出现异常:"+error);        });        return p;    }    function tortoise() {        console.log('乌龟选手');        var p = new Promise(function (resolve, reject) {            setTimeout(function () {                resolve('乌龟赢了');            }, 3000);        });        return p;    }    Promise.race([rabbit(),tortoise()])        .then((result) => {            console.log("比赛结果:"+result);        })}
Vue Cli 脚手架项目请求模块的搭建

在 vue 的基础上,我们可以通过 vue cli 来管理我们的项目。vue cli 方式的优势在于模块之间可以很好地相互引用,通过 package 包来管理配置相关的框架依赖。生态非常丰富,可轻松运用 vue-router 来解决路由跳转等问题。首先第一步是要创建一个 vue cli 项目。

基础安装环境
npm install -g @vue/clivue create helloworld 方式创建项目也可以使用 GUI vue ui 来通过网页手动点击按钮操作来创建项目
package.json 配置
{  "name": "gaoying-cli",  "version": "0.1.0",  "private": true,  "scripts": {    "serve": "vue-cli-service serve",    "build": "vue-cli-service build",    "lint": "vue-cli-service lint"  },  "dependencies": {    "animate.css": "^3.7.2",    "core-js": "^3.4.3",    "vue": "^2.6.10",    "vue-axios": "^2.1.5",    "vue-router": "^3.1.3",    "vuex": "^3.1.2",    "weui.js": "^1.2.1"  },  "devDependencies": {    "@vue/cli-plugin-babel": "^4.1.0",    "@vue/cli-plugin-router": "^4.1.1",    "@vue/cli-plugin-vuex": "^4.1.1",    "@vue/cli-service": "^4.1.0",    "axios": "^0.19.0",    "vue-template-compiler": "^2.6.10",    "weui": "^2.1.3"  },  "eslintConfig": {    "root": true,    "env": {      "node": true    },    "extends": [      "plugin:vue/essential",      "eslint:recommended"    ],    "parserOptions": {      "parser": "babel-eslint"    }  },  "browserslist": [    "> 1%",    "last 2 versions"  ]}
配置 main.js
import Vue from 'vue'import App from './App.vue'import router from './router'import store from './store'import axios from 'axios' //请求网络import VueAxios from 'vue-axios' import weui from 'weui.js' //weuiJsimport 'weui' //weui 样式import ymAPI from '@/assets/js/urlConfig.js' //Apiimport netManager from '@/assets/js/netManager.js' //请求基础参数拼接import ymNativeBridge from '@/assets/js/ymNativeBridge.js' //原生事件交互import animate from 'animate.css'const ymHttp = axios.create({    baseURL: 'https://vendor-api-prod.gaoying.com',     timeout: 1000,    transformRequest: [function(data) {        // Do whatever you want to transform the data        let ret = ''        for (let it in data) {            ret += encodeURIComponent(it) + '=' + encodeURIComponent(data[it]) + '&'        }        return ret    }]});Vue.config.productionTip = falseVue.prototype.$weui = weuiVue.prototype.$ymAPI = ymAPIVue.prototype.$netManager = netManagerVue.prototype.$ymNativeBridge = ymNativeBridgeVue.use(VueAxios, ymHttp,animate)new Vue({  router,  store,  render: h => h(App)}).$mount('#app');
请求 Demo 示例

//和普通 h5 请求网络类似,唯一不同的就是通过挂载到 Vue 上的 axios ,可以通过 this.http 获取。this.netManager 也类似。

execBaseCustomerRequest: function(url, listKey) {   var loading = null;   if (this.pageNumber == 1) {       loading = this.$weui.loading('加载中');       this.gyPageListStart = 0;   }   let pageVue = this; // this 在不同的作用域中指向的对象不同;临时存储 vue 对象   this.$http.post(url, this.$netManager.getRequestParams({       customer_id: this.customerId,       start: this.gyPageListStart,       size: 10,   })).then(function(response) {       if (loading) {           loading.hide();       }       let dataDic = response.data;                if (dataDic.status == 1) {           var arr = pageVue.dataSource;           if (pageVue.pageNumber == 1) {               arr = [];           }           var dataArr = dataDic.data[listKey];           arr = arr.concat(dataArr);           pageVue.gyPageListStart = dataDic.data.start;           pageVue.hasMoreDataFlag = (dataDic.data.more == 1);           pageVue.dataSource = arr;       }else{           pageVue.$weui.topTips(dataDic.errorMsg);       }       setTimeout(function() {           pageVue.requestLoadingFinished = true;       }, 800);       //重置加载完成的状态;   }).catch(function(error) {       console.log(error);   });}
模块之间的引用和导出
import MD5 from './md5.js'export default {    getRequestParams: function(params) {        let userId = localStorage.getItem("userId");        let token = localStorage.getItem("token");        ......    }}//md5.js 文件中 var MD5 = function (string) {    ......}module.exports = MD5//接口配置 urlConfig.js 文件中const ymAPI = {    //客户信息     customerList: "/customer/list/",    customerLogs: "/customer/logs/",    customerCoupons: "/customer/coupons/",    customerOrders: "/customer/orders/",    customerDetail: "/customer/detail/"}module.exports = ymAPI

export 在 js 文件中可以有多个。

//testExport.jsexport const person = { name: "qiugaoying",sex:1, job:"software Programmer"}export const addressInfo = {province:"广东省", city:"guangzhou"}export const introduct = function(){    console.log("my name is qiugaoying");}

export 有多个的时候 ,导入必须用花括号括起来。

import {person,addressInfo} from "../../utils/testExport.js"import * as  allExp from "../../utils/testExport.js"  //加载全部 export,取个别名

** 总结 **

  1. export default 只能导出一个对象。import 和 export 同一 js 文件中可以导入或导出多次。
  2. module.exports 和 exports 都是 node 端在用,两者指向同一内存块,可以导出变量、函数、或者对象。
  3. exports 变量是在模块的文件级作用域内可用的,且在模块执行之前赋值给 module.exports。
H5 和 App 原生交互
//原生调用 appexport default {    callApp:function(handlerMethod, parameters) {        if (!window.WeixinJSBridge || !WeixinJSBridge.invoke) {            var handlerInterface = 'YunMiaoNative';            var dic = {                'handlerInterface': handlerInterface,                'function': handlerMethod, //调用原生的指令                'parameters': parameters //传递的参数;            };            if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) {                window.webkit.messageHandlers[handlerInterface].postMessage(dic);            } else { //安卓                  app.ymAppWebClick(); //dic            }        } else {            //包含微信功能,比如可唤起小程序。        }    },    //原生调用 app 并传递参数给 H5    callbackH5: function(handlerMethod, parameters, callbackMethod) {        if (!window.WeixinJSBridge || !WeixinJSBridge.invoke) {            var handlerInterface = 'YunMiaoH5';            var dic = {                'handlerInterface': handlerInterface,                'function': handlerMethod, //调用原生的指令                'parameters': parameters, //传递的参数;                'callbackMethod': callbackMethod //回调的函数            };            if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) {                window.webkit.messageHandlers[handlerInterface].postMessage(dic);            } else { //安卓                  app.ymAppWebClick(JSON.stringify(dic));            }        } else {            //包含微信功能,比如可唤起小程序。        }    }}

阅读全文: http://gitbook.cn/gitchat/activity/5e146270eb69ea4eda349b34

您还可以下载 CSDN 旗下精品原创内容社区 GitChat App ,阅读更多 GitChat 专享技术内容哦。

FtooAtPSkEJwnW-9xkCLqSTRpBKX

关注
打赏
1688896170
查看更多评论

蔚1

暂无认证

  • 4浏览

    0关注

    4645博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文
立即登录/注册

微信扫码登录

0.3253s