忙带懒,好久没有更新文章了(其实主要是想留给你们一些消化前面文章知识点的时间,哈哈哈)。

我们在前文 《从编程小白到全栈开发:基于框架开发服务端》中,初步学习了如何使用Node.js服务端框架Express来编写后端服务,并基于Express,对我们先前的简易计算器程序的代码进行了一次重构。如果你是个初学者的话,相信通过阅读和实践前面的几篇文章,你已经能开始自己写一些代码了,并能对一个程序的各个组成部分建立起更加清晰直观的认识,知道什么是客户端,什么是服务端。

今天,在这个基础上,我想拓展一下你们对于客户端的理解。如果我没猜错的话,应该很多人都会把网页,移动app,桌面程序等用户直接可以操作的部分,当做客户端。从一个程序的用户角度来说,这种说法是没错的。不过,从程序本身来说的话,客户端的定义就会广泛许多,来看下图:

在该图示意的系统中,我们有多个后端服务(在一个实际的软件系统中,这个是非常常见的),这些后端服务之间也会互相的进行调用;后端服务也会调用其他第三方提供的服务。这种情况下,我们会把提供服务的叫做服务端,调用服务的叫做客户端。因此,该图中的界面UI后端服务1后端服务2在其有限的范围内,都可以被称作客户端:界面UI后端服务1后端服务2的客户端;后端服务1后端服务2第三方服务1的客户端,以此类推。

客户端调用服务端的时候,需要遵循事先的约定,也就是我们常说的协议。到目前为止,我们开发的服务都是基于HTTP协议,所以在客户端我们也都需要使用HTTP协议来发起调用。

在浏览器中调用HTTP服务

在浏览器中,我们通常可以通过<form>表单或XMLHttpRequest的来调用服务端的HTTP服务。

使用<form>

我们先来看一下使用<form>,如何来调用我们之前写的计算器后端服务/calc

在我们的html代码会像是这样:

<form class="calculator" action="/calc" method="GET"><input type="text" id="num1" name="num1"><select id="operator" name="operator"><option value="+">+</option><option value="-">-</option><option value="*">*</option><option value="/">/</option></select><input type="text" id="num2" name="num2"><button type="submit">计算</button>
</form>

在这个表单中,<form>标签上的action属性设置为目标调用的服务路径,method设置为调用所使用的HTTP方法。然后在<form>表单下的<input><select>都需要设置上name属性,它们会被用做调用服务的参数名,传递到服务端。

使用XMLHttpRequest

使用XMLHttpRequest调用的方式,也就是我们耳熟能详的AJAX,其实在我们之前的计算器示例代码中就已经使用了:

function calc() {// 获取id为num1的输入框var num1El = document.getElementById('num1');// 从num1输入框获取文字内容并转换成数字类型var num1 = parseFloat(num1El.value);// 获取id为num2的输入框var num2El = document.getElementById('num2');// 从num2输入框获取文字内容并转换成数字类型var num2 = parseFloat(num2El.value);// 获取id为operator的下拉框var operatorEl = document.getElementById('operator');// 从下拉框获取当前选中的内容var operator = operatorEl.value;// 后端服务的地址var requestUrl = '/calc';// 要发送到后端的数据var requestParams = 'num1=' + num1 + '&num2=' + num2 + '&operator=' + encodeURIComponent(operator);// 把上面的地址和数据拼到一起来var url = requestUrl + '?' + requestParams;// 创建一个XMLHttpRequest对象,通过它来和后端服务进行通信交互var xhr = new XMLHttpRequest();// 设置当后端请求产生反馈后的处理xhr.onreadystatechange = function () {if (xhr.readyState === 4) {// 成功if (xhr.status === 200) {alert('计算结果是:' + xhr.responseText);}// 失败else {alert('请求服务器失败');}}};// 开始发送请求xhr.open('GET', url, true);xhr.send(null);
}

这个代码中,直接使用了XMLHttpRequest的API来进行服务的调用,没有考虑到在不同浏览器上的兼容问题,代码也比较冗长,在现在的实际开发中,我们已经不太会采用了,取而代之的是使用经过良好封装的开源库,如jQuery, axios等。

我们来看一下使用这些开源库的API是如何来实现等价的服务调用功能的。

这是使用jQuery改写成的版本:

function calc() {$.ajax({method: 'get',url: '/calc',data: {num1: parseFloat($('#num1').val()),num2: parseFloat($('#num2').val()),operator: $('#operator').val()}}).then(function (result) {alert('计算结果是:' + result);}).catch(function () {alert('请求服务器失败');});
}

而这是使用axios改写成的版本:

function calc() {axios({method: 'get',url: '/calc',params: {num1: parseFloat(document.getElementById('num1').value),num2: parseFloat(document.getElementById('num2').value),operator: document.getElementById('operator').value}}).then(function (response) {alert('计算结果是:' + response.data);}).catch(function () {alert('请求服务器失败');});
}

可以看到,使用jQuery或axios改写的版本,从代码上来说,要比使用原始XMLHttpRequest API的版本要简洁,而且都支持Promise,所以在写异步流程控制代码方面,显得要方便很多。另外,这些库都考虑到了浏览器之间的兼容问题,所以同样的代码在不同的浏览器上运行,都没什么问题。

在Node.js中调用HTTP服务

看完浏览器端的调用,我们再转到服务端来。在Node.js的服务端代码中,如果要发起对其他HTTP服务的调用的话,Node.js提供了一个叫做http的模块。

我们在Node.js中去调用一个天气预报的API,代码看起来会是这样子的:

const http = require('http');http.get('http://www.weather.com.cn/data/sk/101190401.html', function (req, res) {let result = '';req.on('data', function (data) {result += data;});req.on('end', function () {console.info(result);});
});

执行这段代码,可以得到类似如下的结果:

{"weatherinfo":{"city":"苏州","cityid":"101190401","temp":"17","WD":"东南风","WS":"2级","SD":"44%","WSE":"2","time":"17:05","isRadar":"0","Radar":"","njd":"暂无实况","qy":"1017","rain":"0"}}

是不是也挺简单的?这是Node.js自带的模块,其实还有很多第三方的开源库可以用,比如request,或者是前面提到过的axios(它同时支持浏览器端和Node.js端)。作为全栈JS开发,我们非常希望代码复用性强,风格统一,因此,我推荐无论在浏览器端还是Node.js端,我们都可以统一使用axios来编写HTTP服务调用代码。

所以,我们继续来用axios改写一下上面的代码:

记得先安装一下axios模块:
npm install axios

const axios = require('axios');axios({method: 'get',url: 'http://www.weather.com.cn/data/sk/101190401.html'
}).then(function (response) {console.log(response.data);
}).catch(function () {console.log('请求服务器失败');
});

总结

通过上述简单的例子,希望能让你触类旁通,然后通过自己的深入学习了解,完全掌握客户端和服务端的概念,以及两者之间的内在联系。

点击下载本文的完整代码

新的一年,学习创造新的价值。
欢迎关注一斤代码的系列课程《从编程小白到全栈开发》

从编程小白到全栈开发:服务的调用相关推荐

  1. 从编程小白到全栈开发:基于框架开发服务端

    上文中,我们了解了关于服务器端的一些概念知识,尤其是HTTP协议相关的最基本知识点,今天我想跟大家分享一下在平时正真的开发中,是如何来利用和体现这些内容的. 还记得我在<从编程小白到全栈开发:改 ...

  2. 微信小程序 基础3【组件化开发、自定义组件、全栈开发、使用Express】

    视频地址: https://www.bilibili.com/video/BV1cW411T7t6  [2018]学做小程序- 清华大学 https://www.bilibili.com/video/ ...

  3. 小白都能看懂的实战教程 手把手教你Python Web全栈开发(DAY 1)

    小白都能看懂的实战教程 手把手教你Python Web全栈开发 Flask(Python Web)实战系列之在线论坛系统 第一讲 博主博客文章内容导航(实时更新) 更多优质文章推荐: 收藏!最详细的P ...

  4. 小白如何入门全栈开发

    前言 本教程的主要目的是想从最基础简单的概念入手,记录下自己是如何从小白到入门全栈开发的过程,以便自己查阅. 当然,如果能给后来者带来那么一点点的帮助,那将甚是欣慰. 项目命名 一直挺喜欢内容电商小红 ...

  5. python 全栈开发,Day32(知识回顾,网络编程基础)

    python 全栈开发,Day32(知识回顾,网络编程基础) 一.知识回顾 正则模块 正则表达式 元字符 :. 匹配除了回车以外的所有字符\w 数字字母下划线\d 数字\n \s \t 回车 空格 和 ...

  6. mybatis mapper.xml dtd_全栈开发踩坑之路4-用MyBatis实现服务

    1.前言 上一篇文章介绍了如何设计后端的Mysql数据库:Alex Wang:全栈开发踩坑之路3-MySql数据库设计,本文介绍如何用MyBatis实现后端服务. 本后端项目的Github地址(撰写中 ...

  7. Web全栈开发基础(小白入门版本)

    博客传送门 近几个月认真写了写Web全栈代码,有点小收获这里分享一下.我还做了个PPT,资源路径 欢迎拍砖指点! Web全栈开发是一个听起来很虎的名词.本文从技术层面解释全栈开发,能帮助没有全栈概念, ...

  8. 小白都能看懂的实战教程 手把手教你Python Web全栈开发(DAY 3)

    小白都能看懂的实战教程 手把手教你Python Web全栈开发 Flask(Python Web)实战系列之在线论坛系统 第三讲 这是小白都能看懂的实战教程 手把手教你Python Web全栈开发 的 ...

  9. python视频网站项目_价值2400元的python全栈开发系列Flask Python Web 网站编程视频

    2 e/ b4 F1 c' H$ D! X 价值2400元的python全栈开发系列Flask Python Web 网站编程视频-优品课堂' z3 _1 Y7 ]6 j4 z # p# r# g* ...

最新文章

  1. cath数据库fasta备注_数据库(同源)搜索软件 FASTA 和 BLAST
  2. 04-多核多cluster多系统之间缓存一致性概述
  3. js_调试_01_14 个你可能不知道的 JavaScript 调试技巧
  4. bash for循环_Bash 中的 For 循环
  5. Android 网络通信架构学习
  6. 《权力的游戏》第八季剧情翻水:超40万粉丝请愿重拍
  7. (转)ComputerStyle与currentStyle的区别
  8. ESP8266(3)
  9. Package php5 have no installation candidate。
  10. 小游戏学习--获取已发布微信小游戏源码
  11. R语言实现PVAR(面板向量自回归模型)
  12. Session简单使用
  13. OS | 【四 文件管理】强化阶段大题解构 —— FAT文件系统、UFS文件系统访问文件过程
  14. 配置“终端服务器授权”激活许可证服务器(转)
  15. Matlab中的匿名函数如何使用?
  16. 语音识别karas实现
  17. 【简七理财笔记】第七课:巧用信用卡,该薅的羊毛就要薅
  18. 生如蝼蚁当立鸿鹄之志,命薄似纸应有不屈之心,乾坤未定,你我都是黑马!(祝大家飞黄腾达前程似锦)
  19. 工业物联网的战国时代
  20. 怎么查看服务器里的文件夹,如何查看远程服务器里面的文件夹

热门文章

  1. Go:表驱动单元测试
  2. 杀死系统中的进程kill和killall命令
  3. GCC the GNU
  4. Samba配置文件常用参数详解-OK
  5. const限定符用法汇总
  6. Servlet 3.0对上传的支持
  7. Postgres不同数据库间访问
  8. 杭州恒生数米基金网招聘1-3年本科.NET软件工程师
  9. 非客观书评(三)——《ARM Cortex-M3 权威指南》
  10. Iframe的高级操作