【以太坊开发-04】Node.js介绍

【以太坊开发-04】Node.js介绍,第1张

1.定义变量

使⽤ const 来定义⼀个常量,常量也就是不能被修改,不能被重新赋值的变量。

使⽤ let 来定义⼀个变量,⽽不要再使⽤ var 了,因为 var 有很多坑;可以认为 let 就是修 复了bug的 var 。⽐如,var允许重复声明变量⽽且不报错;var的作⽤域让⼈感觉疑惑。最佳实践:优先⽤ const ,如果变量需要被修改才⽤ let ;要理解⽬前很多早期写的项⽬中仍 然是⽤ var 。
var i = 10;
console.log("var :", i);
var i = 100;
console.log("var :", i);

function test() {
    var m = 10;
    console.log("test m :", m);
}

test(); //console.log("test outside :", m); 
let j = "hello"
console.log("j :", j);
j = "HELLO"
console.log("j :", j);
const k = [1, 2, 3, 4];
console.log("k0 :", k);
k[0] = 100;
console.log("k1 :", k);
2.解构赋值

ES6 允许我们按照⼀定模式,从数组和对象中提取值,对变量进⾏赋值,这被称为解构 (Destructuring)

数组的解构赋值
const arr = [1, 2, 3] //我们得到了⼀个数组 
let [a, b, c] = arr //可以这样同时定义变量和赋值 
console.log(a, b, c); // 1 2 3 
对象的解构赋值(常⽤)
const obj = { name: '俊哥',address:'深圳', age: '100'} //我们得到了⼀个对象 
let {name, age} = obj //可以这样定义变量并赋值 
console.log(name, age); //俊哥 100 
函数参数的解构赋值(常⽤)
const person = {name: '⼩明', age: 11}

function printPerson({name, age}) { // 函数参数可以解构⼀个对象 
    console.log(`姓名:${name} 年龄:${age}`);
}

printPerson(person) // 姓名:⼩明 年龄:11
3. 函数扩展

ES6对函数增加了很多实⽤的扩展功能。

参数默认值,从ES6开始,我们可以为⼀个函数的参数设置默认值, go语⾔有默认值吗?
 function foo(name, address = '深圳') { 
  console.log(name, address); 
  }
  foo("⼩明") // address将使⽤默认值 
  foo("⼩王", '上海') // address被赋值为'上海'` 
箭头函数,将 function 换成 => 定义的函数,就是箭头函数 只适合⽤于普通函数,不要⽤在构造函数,不要⽤在成员函数,不要⽤着原型函数
function add(x, y) {
    return x + y
}//演示⾃执⾏函数 
//函数也是变量,可以赋值 
// 这个箭头函数等同于上⾯的add函数 
(x, y) => x + y; // 如果函数体有多⾏,则需要⽤⼤括号包裹 
(x, y) => {
    if (x > 0) {
        return x + y
    } else {
        return x - y
    }
}
4. Class继承

由于js⼀开始被设计为函数式语⾔,万物皆函数。所有对象都是从函数原型继承⽽来,通过 继承某个函数的原型来实现对象的继承。但是这种写法会让新学者产⽣疑惑,并且和传统的OOP 语⾔差别很⼤。ES6 封装了class语法来⼤⼤简化了对象的继承。

class Person {
    constructor(name, age) {
        this.name = name
        this.age = age
    }// 注意:没有function关键字
    sayHello() {
        console.log(`⼤家好,我叫${this.name}`);
    }
}

class Man extends Person {
    constructor(name, age) {
        super(name, age)
    }

//重写⽗类的⽅法
    sayHello() {
        console.log('我重写了⽗类的⽅法!');
    }
}

let p = new Person("⼩明", 33) //创建对象
p.sayHello() // 调⽤对象p的⽅法,打印 ⼤家好,我叫⼩明
let m = new Man("⼩五", 33)
m.sayHello() // 我重写了⽗类的⽅法!
5. 理解NodeJS的事件驱动和异步IO

NodeJS在⽤户代码层,只启动⼀个线程来运⾏⽤户的代码==(go语⾔?)==。每当遇到耗时的 IO(⽂件IO,⽹络IO,数据库IO) *** 作,⽐如⽂件读写,⽹络请求,则将耗时 *** 作丢给底层的事件循 环去执⾏,⽽⾃⼰则不会等待,继 续执⾏下⾯的代码。当底层的事件循环执⾏完耗时IO时,会执⾏我 们的回调函数来作为通知。(写demo)

同步就是你去银⾏排队办业务,排队的时候啥也不能⼲(阻塞);异步就是你去银⾏⽤取号机取了⼀个 号,此时你可以⾃由的做其他事情,到你的时候会⽤⼤喇叭对你进⾏事件通知。⽽银⾏系统相当于底 层的事件循环,不断的处理耗时的业务(IO)。

6. 回调函数 Node.js 异步编程的直接体现就是回调回调函数在完成任务后就会被调⽤,Node 使⽤了⼤量的回调函数,Node 所有 API 都⽀持回调函 数。回调函数⼀般作为参数的最后⼀个参数出现。我们可以⼀边读取⽂件,⼀边执⾏其他命令,在⽂件读取完成后,我们将⽂件内容作为回调函数的参 数返回。这样在执⾏代码时就没有阻塞或等待⽂件 I/O *** 作。这就⼤⼤提⾼了 Node.js 的性能,可以 处理⼤量的并发请求。
 function foo1(name, age, callback) { } 
 function foo2(value, callback1, callback2) { }
同步调用(阻塞)

请事先在当前⽬录下准备⽂件"input.txt",写⼊任意数据。

 var fs = require("fs"); 
 data = fs.readFileSync('input.txt'); 
 console.log(data.toString()); 
 console.log("程序执⾏结束!"); 
异步调用(非阻塞)
var fs = require("fs");
fs.readFile('input.txt', function (err, data) {
    if (err) return console.error(err);
    console.log(data.toString());
});
console.log("程序执⾏结束!");
7.模块系统

为了让Node.js的⽂件可以相互调⽤,Node.js提供了⼀个简单的模块系统 ⼀个⽂件就是⼀个模块,使⽤export关键字实现

//hello.js
let Hello = () => {
    console.log("hello world!")
}
module.exports = Hello;
//main.js var Hello = require('./hello'); 
Hello();
8. path模块 path模块供了⼀些⼯具函数,⽤于处理⽂件与⽬录的路径path.basename :返回⼀个路径的最后⼀部分path.dirname :返回⼀个路径的⽬录名path.extname :返回⼀个路径的扩展名 path.join :⽤于拼接给定的路径⽚段path.normalize :将⼀个路径正常化path.resolve([from …], to)
var path = require("path");
// 格式化路径 
console.log('normalization : ' + path.normalize('/test/test1//2slashes/1slash/tab/. .'));
// 连接路径 
console.log('joint path : ' + path.join('/test', 'test1', '2slashes/1slash', 'tab', '..'));
// 转换为绝对路径 
console.log('resolve : ' + path.resolve('main.js'));
// 路径中⽂件的后缀名 
console.log('ext name : ' + path.extname('main.js'));
9. fs模块

⽂件 *** 作相关的模块

fs.stat/fs.statSync :访问⽂件的元数据,⽐如⽂件⼤⼩,⽂件的修改时间fs.readFile/fs.readFileSync :异步/同步读取⽂件fs.writeFile/fs.writeFileSync :异步/同步写⼊⽂件fs.readdir/fs.readdirSync :读取⽂件夹内容fs.unlink/fs.unlinkSync :删除⽂件fs.rmdir/fs.rmdirSync :只能删除空⽂件夹,思考:如何删除⾮空⽂件夹?
– 使⽤ fs-extra 第三⽅模块来删除。fs.watchFile :监视⽂件的变化
let fs = require('fs');
var filename = './testfile.txt';

//同步读取
var data = fs.readFileSync(filename);
console.log(data.toString());

//异步读取
fs.readFile(filename, function (err, data) {
    console.log("========= read done!");
    console.log(data.toString())
});
console.log("111111111111");

//打开⽂件
fs.open(filename, 'r+', function (err, fd) {
    if (err) {
        return console.err("open failed!");
    }
    console.log("open ok!");
})
fs.stat(filename, function (err, stat) {
    console.log("is file :" + stat.isFile());
    console.log("is dir :" + stat.isDirectory());
})

var output = './output.txt';
//同步写⽂件
var data = "你好"
var res = fs.writeFileSync(output, data)
console.log("res :", res); //undefine
//异步写文件
fs.writeFile(output, data, function (err) {
    if (err) {
        //console.log("")
    }
    console.log("writeFile write ok!!!")
})
fs.appendFile(output, data, function (err) {
    if (err) {
        //console.log("")
    }
    console.log("appendFile ok!!!")
})
}
10. Promise和asnyc/await

虽然异步和回调的编程⽅式能充分利⽤CPU,但是当代码逻辑变的越来越复杂后,新的问题出现了。 请尝试⽤异步的⽅式编写以下逻辑代码:
先判断⼀个⽂件是⽂件还是⽬录,如果是⽬录就读取这个⽬录下的⽂件,找出结尾是txt的⽂件, 然后获取它的⽂件⼤⼩。
恭喜你,当你完成上⾯的任务时,你已经进⼊了终极关卡:Callback hell回调地狱!
为了解决Callback hell的问题, Promise 和 async/await 诞⽣。

promise 的作⽤是对异步回调代码包装⼀下,把原来的⼀个回调函数拆成2个回调函数,这样的 好处是可读性更好。语法如下:
语法注意:Promise内部的resolve和reject⽅法只能调⽤⼀次,调⽤了这个就不能再调⽤了那个; 如果调⽤,则⽆效。
 // 创建promise对象
let readFilePromise = new Promise(function (resolve, reject)=>{
    // 在异步 *** 作成功的情况选调⽤resolve,失败的时候调⽤reject
    fs.readFile('xxx.txt', (err, data) => {
        if (err) {
            reject(err)
        } else {
            resolve(data.toString())
        }
    })
});
// 使⽤promise
readFilePromise.then((text) => {
    //then⾥⾯就是我们传给Promise的resolve
    // then⽅法是当Promise内部调⽤了resolve的时候执⾏
    //then有两个参数,then(onResolve, onReject),⼀般写第⼀个即可,第⼆个通过catch来处理 //
}).catch((err) => {
    //catch⽅法是当Promise内部调⽤了reject的时候执⾏ 
    console.log(err);
})
async/await 的作⽤是直接将Promise异步代码变为同步的写法,注意,代码仍然是异步的。这 项⾰新,具有⾰命性的意义。语法要求:
–await 只能⽤在 async 修饰的⽅法中,但是有 async 不要求⼀定有 await 。
–await 后⾯只能跟 async ⽅法和 promise 。 假设拥有了⼀个promise对象,现在使⽤async/await可以这样写:
async function asyncDemo() {
    try {
        // 当promise的then⽅法执⾏的时候 
        let text = await readFilePromise
        // 当你⽤promise包装了所有的异步回调代码后,就可以⼀直await,真正意义实现了以同步 的⽅式写异步代码 
        console.log('异步道明执⾏');
    } catch (e) {
        // 捕获到promise的catch⽅法的异常 
        console.log(e);
    }
}

asyncDemo()
console.log('我是同步代码');

⼩任务 使⽤promise和async/await来重写上⾯的逻辑代码,来感受⼀下强⼤的⼒量吧!。 异步代码的终极写法: 1. 先使⽤ promise 包装异步回调代码,可使⽤node提供的 util.promisify ⽅法; 2. 使⽤ async/await 编写异步代码。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/1498592.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-25
下一篇 2022-06-25

发表评论

登录后才能评论

评论列表(0条)

保存