从编程小白到全栈开发:改造为全栈计算器

简介: 上一次,我们编写了一个纯前端实现的简易计算器,这次,我们就假装这个计算器在前端运行起来太吃力,客户端的资源完全不够用来进行1+1等于几这种复杂的计算。我们得借助强大的服务器(其实就是我们现在正在用来写代码的这台小破电脑)来完成我们的计算任务。

上一次,我们编写了一个纯前端实现的简易计算器,这次,我们就假装这个计算器在前端运行起来太吃力,客户端的资源完全不够用来进行1+1等于几这种复杂的计算。我们得借助强大的服务器(其实就是我们现在正在用来写代码的这台小破电脑)来完成我们的计算任务。

好,开工!

第一步:把计算任务发给后端

在我们之前写的计算器代码中,有一个名为calc的JS函数,负责从页面上获取用户的输入内容,并进行数学运算。现在,我们要改造它,让它只负责获取用户输入内容,并不做运算,运算的工作,将发往服务器。来看下我是怎么改造它的:

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的对象,向一个我们暂时还没实现的后端服务(/calc)发送服务请求,把用户输入的两个数字和运算符号发送到后端,等待后端进行处理,并在后端服务有反馈的时候(可能是计算完成,也可能是失败)在页面上给出结果或错误提示。

第二步:创建后端服务

改造前端页面后,我们要来编写这个服务器端的代码了。在这之前,需要先提醒一个事情:就是我们用了XMLHttpRequest来和服务器进行沟通的时候,浏览器会要求我们的页面也必须是要在服务器上,也就是说我们之前直接把html拖进浏览器或通过菜单里“打开”运行的方式,会让XMLHttpRequest不能正常工作。

本地打开的html文件不能让XMLHttpRequest正常工作

下面这种形式才能正常工作:

需要以网址的方式访问

所以在创建我们的后端服务代码的时候,我们会同时来解决这件事情。

我们先创建一个server.js,它将是我们的后端Node.js代码。然后我们来组织一下,把我们的calculator.html和server.js放在一起,都放到同一个文件夹中,比如放到一个叫calculator的文件夹下:

放在同一个文件夹下

接着,我们先来做后端的第一个功能,就是让我们的calculator.html能在浏览器里通过http://localhost:8888这样的网址进行访问。

const http = require('http');

const server = http.createServer((req, res) => {
    res.end('working!!!');
});

server.listen(8888, () => {
    console.log('server is listening on port 8888 ...')
});

Node.js提供了叫做http的API模块,通过它可以很容易的创建一个提供HTTP服务的后端程序。像上面那样,我们通过http.createServer函数,就创建了一个最简单的后端,然后让它监听在8888端口上,等待请求的到来并作出响应。

你可以通过VS Code来启动这个后端程序,在之前的文章中我已经告诉过大家怎么使用了;你也可以通过windows或Mac的命令行终端来运行这个server.js,方法就是在命令行中,进入你存放server.js的目录,然后执行node server.js,成功运行的话,你就能看到如下所示的内容了:

使用命令行终端运行

然后,打开你的浏览器,在地址栏输入http://localhost:8888,正常的话,就能看到'working!!!'了。

Working

接下来,我们要根据访问的地址不同,后端要进行不同的反馈,比如默认的http://localhost:8080,应该显示我们之前做的那个页面,而http://localhost:8080/calc,应该要执行我们期望的数学运算。

const http = require('http');
const url = require('url');
const querystring = require('querystring');
const fs = require('fs');

const server = http.createServer((req, res) => {
    var parsedURL = url.parse(req.url);

    // 获取请求的服务路径
    var pathname = parsedURL.pathname;

    // 如果是根路径/,则输出calculator.html
    if (pathname === '/') {
        // 读取文件calculator.html内容
        fs.readFile(__dirname + '/calculator.html', (err, data) => {
            // 设置服务响应头,代表响应的内容是HTML格式的
            res.writeHead(200, {
                'Content-Type': 'text/html'
            });

            // 读取文件失败,则发送这段html内容
            if (err) {
                res.end("<h4>加载HTML文件失败<h4>");
            } 
            // 读取文件成功,则发送文件中的html内容
            else {
                res.end(data.toString());
            }
        });
    } 
    
    // 如果是路径/calc,则处理运算逻辑
    else if (pathname === '/calc') {
        // 从请求中,分离出从前端发送给后端的用户输入数据
        var params = querystring.parse(parsedURL.query);

        var num1 = parseFloat(params.num1);
        var num2 = parseFloat(params.num2);
        var operator = params.operator;

        var result = 0;

        // 和之前一样的计算逻辑
        if (operator === '+') {
            result = num1 + num2; // 相加
        } else if (operator === '-') {
            result = num1 - num2; // 相减
        } else if (operator === '*') {
            result = num1 * num2; // 相乘
        } else if (operator === '/') {
            result = num1 / num2; // 相除
        }

        // 设置服务响应头,代表响应的内容是纯文本格式的
        res.writeHead(200, {
            'Content-Type': 'text/plain'
        });

        // 发送计算结果(必须是字符串形式)
        res.end('' + result);
    }
});

server.listen(8888, () => {
    console.log('server is listening on port 8888 ...')
});

好,让我们重新运行一下这个server.js,然后在浏览器中访问http://localhost:8080,我们熟悉的计算器界面又回来了!

计算器界面

尝试输入点内容计算一下,是不是跟之前一样,也能出现计算结果?只不过这一次,它的计算是在Node.js这边的后端服务中进行的啦!

好好消化一下吧,不明白的地方可以直接向我发问哦!

下一次开始,我将稍微讲点基础性知识(不是基础“性知识”!),让你能更好的明白这几篇文章中涉及到的内容。

就算你现在一脸懵逼,你也会成为专家。
欢迎关注一斤代码的系列课程《从编程小白到全栈开发》

目录
相关文章
|
2月前
|
测试技术 Android开发 开发者
移动应用开发之旅:从概念到上线的全栈探索
【9月更文挑战第36天】在这个数字时代,移动应用已经成为我们生活中不可或缺的一部分。本文将带领读者踏上一场精彩的旅程,从最初的构想到最终的应用上线,深入探讨移动应用开发的各个环节。我们将一起揭开移动操作系统的神秘面纱,了解它们如何支撑起整个移动生态系统。通过具体的代码示例和实操建议,本文旨在为初学者提供一份实用的指南,同时给予有经验的开发者一些新的启示。让我们一起构建更智能、更互联的世界吧!
|
5月前
|
前端开发
全栈技术实践问题之全栈开发带来的主要好处是什么
全栈技术实践问题之全栈开发带来的主要好处是什么
|
7月前
|
小程序 前端开发 API
小程序全栈开发中的前后端分离实践
【4月更文挑战第12天】本文探讨了小程序全栈开发中的前后端分离实践,强调其能提升开发效率、代码可维护性和可扩展性。文中详细阐述了接口设计、数据交互、前端渲染、后端处理以及团队协作的重要性,并指出统一的API接口、使用前端框架和后端服务器是关键。通过这种模式,开发者能更高效地掌握小程序开发,打造高质量应用。
165 0
|
存储 开发框架 小程序
【全栈小程序开发路线】手把手教你入门小程序开发,小白必看!
以下内容是结合我项目中实战经验,踩坑记录,大量时间学习小程序的积累,总结分享给大家。 学习路线包括前端基础、小程序开发框架、UI组件库、云开发、周边生态以及插件这几个纬度,学完这些,你也能全栈开发一个属于自己的产品。
581 0
|
Cloud Native 算法 测试技术
你写过的最蠢的代码是?——全栈开发篇
你写过的最蠢的代码是?——全栈开发篇
60 0
|
移动开发 前端开发 Java
|
机器学习/深度学习 人工智能 前端开发
前端已死?全栈当立?取法于中,仅得其下。
开篇明义,前端已死?根本就是扯淡。前端技术精微渊深,驳杂宽广,除了基础的 HTML、CSS 和 JavaScript 技术外,前端技术还涉及到许多其他相关技术和工具,比如前端框架、UI 库、自动化构建工具、代码管理工具等等。这些技术并没有死,反而生态圈愈发健壮,但为什么前端已死的论调甚嚣尘上?
前端已死?全栈当立?取法于中,仅得其下。
|
缓存 监控 Ubuntu
全栈软件测试工程师宝典连载(8)(上)
全栈软件测试工程师宝典连载(8)(上)
124 0
全栈软件测试工程师宝典连载(8)(上)
|
存储 监控 Devops
全栈软件测试工程师宝典连载(8)(下)
全栈软件测试工程师宝典连载(8)(下)
91 0
全栈软件测试工程师宝典连载(8)(下)
|
前端开发 JavaScript 架构师
我们真的需要全栈开发吗?
Web应用程序的开发涉及许多活动,例如: 捕获用户故事