html代码:

HTML5初识Canvas

TypeScript在node项目中的实践

TypeScript可以理解为是JavaScript的一个超集,也就是说涵盖了所有JavaScript的功能,并在之上有着自己独特的语法。
最近的一个新项目开始了TS的踩坑之旅,现分享一些可以借鉴的套路给大家。

图片 1图片 2

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Canvas示例</title>
    <!--[if lte IE 8]><script type="text/javascript" src="excanvas.js"></script><![endif]-->
</head>

<body>
    <p>Canvas的用途:</p>
    <p>动态生成和展示图形、图表、图像以及动画</p>
    <p>性能非常好:不需要将所绘制的图像中的每个图元当做对象存储。API相对简单</p>
    <p>canvas默认会创建一块矩形区域 默认尺寸 300 X 150(px)</p>
    <p>canvas的坐标默认是0,0 也叫原点</p>
    <p>canvas也可以通过css的方式增加边框、内边距、外边距等</p>
    <p>现在的大部分浏览器已经支持canvas<br /> 
老版本的IE不支持,可以使用一个js库来做兼容:explorercanvas.js <br> 
js库地址:https://github.com/arv/ExplorerCanvas
    </p>

    <canvas id="test" style="border:1px solid;" width="200" height="200">
        当浏览器不支持canvas时会显示这段文字,这里还可以使用图片代替
    </canvas>
    <script>
        function drawTest() {
            //获取canvas元素及绘图上下文对象
            var canvas = document.getElementById('test');
            var context = canvas.getContext('2d');

            //用绝对坐标来创建一条路径
            context.beginPath();
            context.moveTo(70, 140);
            context.lineTo(140, 70);
            context.stroke();
        }
        window.addEventListener("load", drawTest, true);
    </script>
</body>

</html>

为什么选择TS

作为巨硬公司出品的一个静态强类型编译型语言,该语言已经出现了几年的时间了,相信在社区的维护下,已经是一门很稳定的语言。
我们知道,JavaScript是一门动态弱类型解释型脚本语言,动态带来了很多的便利,我们可以在代码运行中随意的修改变量类型以达到预期目的。
但同时,这是一把双刃剑,当一个庞大的项目出现在你的面前,面对无比复杂的逻辑,你很难通过代码看出某个变量是什么类型,这个变量要做什么,很可能一不小心就会踩到坑。

而静态强类型编译能够带来很多的好处,其中最重要的一点就是可以帮助开发人员杜绝一些马虎大意的问题:
图片 3
图为rollbar统计的数千个项目中数量最多的前十个异常

不难看出,因为类型不匹配、变量为空导致的异常比你敢承认的次数要多。
譬如
图片 4
而这一点在TS中得到了很好的改善,任何一个变量的引用,都需要指定自己的类型,而你下边在代码中可以用什么,支持什么方法,都需要在上边进行定义:
图片 5
这个提示会在开发、编译期来提示给开发者,避免了上线以后发现有问题,再去修改。

另外一个由静态编译类型带来的好处,就是函数签名。
还是就像上边所说的,因为是一个动态的脚本语言,所以很难有编辑器能够在开发期间正确地告诉你所要调用的一个函数需要传递什么参数,函数会返回什么类型的返回值。

图片 6

而在TS中,对于一个函数,首先你需要定义所有参数的类型,以及返回值的类型。
这样在函数被调用时,我们就可以很清晰的看到这个函数的效果:
图片 7

这是最基础的、能够让程序更加稳定的两个特性,当然,还有更多的功能在TS中的:TypeScript
| Handbook

<!DOCTYPE html>
<html>

    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>火星黑洞</title>
    </head>

    <body>
        <div>
            <audio autoplay></audio>
            <input onclick="startRecording()" type="button" value="录音" />
            <input onclick="stopRecording()" type="button" value="停止" />
            <input onclick="playRecording()" type="button" value="播放" />
            <input onclick="uploadAudio()" type="button" value="提交" />
            <br />
            <div id="recordingslist"></div>
        </div>
        <script type="text/javascript" src="js/HZRecorder.js"></script>
        <script>
            var recorder;

            var audio = document.querySelector('audio');

            function startRecording() {
                HZRecorder.get(function(rec) {
                    recorder = rec;
                    recorder.start();
                }, {
                    sampleBits: 16,
                    sampleRate: 16000
                });
            }

            function stopRecording() {
                recorder.stop();
                var blob = recorder.getBlob();
                var url = URL.createObjectURL(blob);
                var div = document.createElement('div');
                var au = document.createElement('audio');
                var hf = document.createElement('a');

                au.controls = true;
                au.src = url;
                hf.href = url;
                hf.download = new Date().toISOString() + '.wav';
                hf.innerHTML = hf.download;
                div.appendChild(au);
                div.appendChild(hf);
                recordingslist.appendChild(div);
            }

            function playRecording() {
                recorder.play(audio);
            }

            function uploadAudio() {
                recorder.upload("Handler1.ashx", function(state, e) {
                    switch(state) {
                        case 'uploading':
                            //var percentComplete = Math.round(e.loaded * 100 / e.total) + '%';
                            break;
                        case 'ok':
                            //alert(e.target.responseText);
                            alert("上传成功");
                            break;
                        case 'error':
                            alert("上传失败");
                            break;
                        case 'cancel':
                            alert("上传被取消");
                            break;
                    }
                });
            }
        </script>

    </body>

</html>

 

TypeScript在node中的应用

在TS的官网中,有着大量的示例,其中就找到了Express版本的例子,针对这个稍作修饰,应用在了一个
koa 项目中。

View Code

环境依赖

在使用TS之前,需要先准备这些东西:

  1. VS
    code
    ,同为巨硬公司出品,本身就是TS开发的,遂该编辑器是目前对TS支持度最高的一个
  2. Node.js 推荐8.11版本以上
  3. npm i -g typescript,全局安装TS,编译所使用的tsc命令在这里
  4. npm i -g nodemon,全局安装nodemon,在tsc编译后自动刷新服务器程序
  • 官方手册
  • 官方Express示例

以项目中使用的一些核心依赖:

  1. reflect-metadata
    大量装饰器的包都会依赖的一个基础包,用于注入数据
  2. routing-controllers: 使用装饰器的方式来进行koa-router的开发
  3. sequelize: 抽象化的数据库操作
  4. sequelize-typescript: 上述插件的装饰器版本,定义实体时使用

HZRecorder.js

项目结构

首先,放出目前项目的结构:

.
├── README.md
├── copy-static-assets.ts
├── nodemon.json
├── package-lock.json
├── package.json
├── dist
├── src
│   ├── config
│   ├── controllers
│   ├── entity
│   ├── models
│   ├── middleware
│   ├── public
│   ├── app.ts
│   ├── server.ts
│   ├── types
│   └── utils
├── tsconfig.json
└── tslint.json

 

src为主要开发目录,所有的TS代码都在这里边,在经过编译过后,会生成一个与src同级的dist文件夹,这个文件夹是node引擎实际运行的代码。
src下,主要代码分为了如下结构(依据自己项目的实际情况进行增删):

# folder desc
1 controllers 用于处理接口请求,原appsroutes文件夹。
2 middleware 存放了各种中间件、全局 or 自定义的中间件
3 config 各种配置项的位置,包括端口、log路径、各种巴拉巴拉的常量定义。
4 entity 这里存放的是所有的实体定义(使用了sequelize进行数据库操作)。
5 models 使用来自entity中的实体进行sequelize来完成初始化的操作,并将sequelize对象抛出。
6 utils 存放的各种日常开发中提炼出来的公共函数
7 types 存放了各种客制化的复合类型的定义,各种结构、属性、方法返回值的定义(目前包括常用的Promise版redis与qconf)

发表评论

电子邮件地址不会被公开。 必填项已用*标注