个性化阅读
专注于IT技术分析

Node开发人员犯的5大错误

本文概述

Node是编写后端的绝佳平台。除非你做得不好。

根据你碰巧站在栅栏的哪一边, Node可能是Web开发世界上发生的最好的事情或最坏的事情。但是尽管有很多意见, 但没有争论Node的流行。它的普及速度比任何人都快, 甚至包括它的创建者(他在另外一次悲观的采访中都这样说)!

在撰写本文时, 它是启动新应用程序的默认平台, 我承认这通常是一群人的心态, 但最终的结果是, 与其他传统脚本语言相比, Node中的工作机会更多, 资金更多, 项目更多。

不幸的是, 当有人要求我向他们推荐用于Web开发或新启动产品的入门堆栈时, Node是我的第一推荐, 即使我精通PHP和Laravel。

Node开发人员犯的5大错误2

如果可以允许我继续讲一点(由于是我, 我会这样吗?), Node讨厌者会说一点, 他们说自己喜欢的Web堆栈可以完成与Node一样的工作, 但是反之亦然。然后是异步编程和事件, 这些东西从第一天起就被移植到Node中, 其他生态系统现在正拼命尝试复制。

今天, 我们在PHP和Python中提供了异步选项, 但是不幸的是, 现有的流行库的核心是完全同步的, 因此几乎就像你在与系统作斗争。但是无论如何, 足够的怒气一天。 ????

因此, 如果你是Node开发人员(初学者或熟悉的人), 则很可能是犯了这些对你的应用程序产生负面影响的重大错误之一。这可能是因为你不熟悉Node中更好的做事方式, 或者仅仅是你从其他生态系统继承下来的习惯。

不尊重事件循环

当一个人迁移到Node时, 部分原因是因为他们听说过LinkedIn如何使用Node进行扩展的故事, 或者他们看到了基准测试, 这些基准显示Node在每秒处理请求或处理请求方面围绕PHP, Ruby等运行打开插座连接。

因此, 他们构建了自己的应用程序, 并期望与他们梦same以求的爆炸性响应时间相同的响应时间, 只是没有发生任何反应。

造成这种情况的主要原因之一是无法正确理解事件循环。考虑以下代码, 该代码从数据库中获取一组书籍, 然后按总页数对其进行排序:

db.Library.get(libraryId, function(err, library) {
    let books = library.books;
    books.sort(function(a, b) {
        return a.pages < b.pages ? -1 : 1
    });
});

我同意该代码对书本排序数组没有任何作用, 但这不是重点。关键是, 这种无害的代码足以在你开始处理数量不小的书籍时立即炸毁事件循环。

原因是事件循环旨在执行非阻塞I / O。一个很好的例子是在披萨店的披萨包装工–这个人专门切割披萨, 将盖子折叠到交货盒中, 放入比萨, 贴上正确的标签, 然后将其推向交货人员。

太好了吧?就像Node!

Node开发人员犯的5大错误4

但是考虑一下如果这个人还需要混合, 准备和包装调味料会发生什么。根据流程的复杂程度, 比萨的包装率将降低到三分之一, 甚至可能完全停止。

这就是”阻塞”任务的意思-只要Node只需传递信息, 它就是非常理想的最佳选择, 但是一旦需要进行大量的计算, 它就会停止, 并且一切否则必须等待。发生这种情况是因为事件循环是单线程的(此处有更多详细信息。)

因此, 无论事件多么重要, 都不要在事件循环中执行计算。我的意思是, 将数字相加并取平均值是可以的, 但是大型数据集将使你的Node应用程序爬行。

希望异步代码能够合作

考虑以下非常简单的Node示例, 该示例从文件读取数据并显示数据:

const fs = require('fs');

let contents = fs.readFile('secret.txt', (err, data) => {
    return data;
});

console.log('File contents are: ');
console.log(contents);

接触经典语言(如PHP, Python, Perl, Ruby, C ++等)将使你应用常识, 即在此代码运行之后, 变量内容将具有文件的内容。但是, 当你实际执行代码时, 会发生以下情况:

Node开发人员犯的5大错误6

我们得到未定义的(<slow clap>)。这是因为虽然你可能会很在意Node, 但它的异步特性并不在乎你(这只是在开玩笑!请不要在此处spa垃圾评论)。我们的工作是了解其异步性质并使用它。 readFile()是一个异步函数, 这意味着一旦调用它, Node事件循环就将工作转移到文件系统组件并继续进行。

读取文件后, 它确实会返回到函数, 但是到那时, 内容被视为未初始化的变量, 因此包含未定义的内容。正确的方法是在回调函数中处理文件数据, 但是由于这不是Node教程, 因此我无法详细介绍。 ????

回调, 该回调调用已调用的回调。 。 。

JavaScript比其他任何主流的主流语言都更接近于函数式编程(事实上, 无论怎么说, 在面向对象的设计和功能方面, 它是我的最爱-我将其置于Python, PHP, Perl, Java和甚至在编写”令人愉快的”代码时也使用Ruby)。

也就是说, 与其他语言相比, 功能获得了更多的公民权利。再加上异步代码可以通过为你提供回调函数而起作用的事实, 最后我们得到了称为”回调地狱”的灾难秘诀。

这是我在Quora上遇到的一些示例电子代码。你觉得呢?

var options;

require('electron').app.once(
    'ready', function () {

        options = {
            frame: false, height: 768, width: 1024, x: 0, y: 0
        };

        options.BrowserWindow = require('electron').BrowserWindow;
        options.browserWindow = new options.BrowserWindow(options);
        options.browserWindow.loadURL('http://electron.atom.io');
        options.browserWindow.webContents.once(
            'did-stop-loading', function () {
                options.browserWindow.capturePage(
                    options, function (data) {
                        require('fs').writeFileSync(
                            '/tmp/screenCapture.testExampleJs.browser..png', data.toPng()
                        );

                        process.exit(0);
                    }
                );
            }
        );
    }
);

如果你遇到困难, 请加入俱乐部!

函数内部函数内部的函数很难理解, 也很难推理, 这就是为什么它被称为”回调地狱”(我想地狱是一个让人迷惑的地方!)。尽管从技术上讲这是可行的, 但是你可以通过对理解和维护的任何尝试使代码永不过时。

有许多避免回调地狱的方法, 包括Promises和Reactive Extensions。

不使用所有CPU内核

现代处理器具有几个核心-2, 4, 8, 16, 32。 。 。人数不断攀升。

Node开发人员犯的5大错误8

但这不是Node创建者发布Node时想到的。结果, Node是单线程的, 这意味着它在单个线程(或进程, 如果要调用它, 尽管它们并不相同)中运行, 并且仅使用一个CPU内核。

这意味着, 如果你从教程, 朋友和代码片段中学习到Node, 并且将你的应用程序部署在8核服务器上, 那么你将浪费7/8的处理能力!

不用说, 这是一个巨大的浪费。如果你遵循这种方法, 最终只需要购买一台服务器就可以购买八台服务器。就是说, 每月花16, 000美元就能赚到2, 000美元(金钱的损失总是很痛苦的, 对吧?)。当解决方案非常简单时, 可以使用所有这些:使用集群模块。

我无法在这里进行所有详细介绍, 但这是一种简单的技术, 可以检测当前计算机具有多少个内核, 然后启动那么多Node实例。检测到错误后, 实例将重新启动。实施起来很简单(此处有教程):

var cluster = require('cluster');

if(cluster.isMaster) {
    var numWorkers = require('os').cpus().length;

    console.log('Master cluster setting up ' + numWorkers + ' workers...');

    for(var i = 0; i < numWorkers; i++) {
        cluster.fork();
    }

    cluster.on('online', function(worker) {
        console.log('Worker ' + worker.process.pid + ' is online');
    });

    cluster.on('exit', function(worker, code, signal) {
        console.log('Worker ' + worker.process.pid + ' died with code: ' + code + ', and signal: ' + signal);
        console.log('Starting a new worker');
        cluster.fork();
    });
} else {
    var app = require('express')();
    app.all('/*', function(req, res) {res.send('process ' + process.pid + ' says hello!').end();})

    var server = app.listen(8000, function() {
        console.log('Process ' + process.pid + ' is listening to all incoming requests');
    });
}

如你所见, cluster.fork()发挥了神奇的作用, 其余的只是监听几个基本的集群事件并进行必要的清理。

不使用TypeScript

好的, 这不是一个错误, 因此, 已经有很多Node应用程序在使用TypeScript编写, 并且正在编写中。

就是说, TypeScript提供了Node始终需要的保证和内心的平静, 在我看来, 如果你在2019年为Node开发并且不使用TypeScript(尤其是当MEAN堆栈中的A(Angular)移动时, 这是一个错误)到TypeScript)。

过渡很平缓, TypeScript几乎完全像你所知道的JavaScript, 并带有类型, ES6和其他一些检查的保证:

//   /lib/controllers/crmController.ts
import * as mongoose from 'mongoose';
import { ContactSchema } from '../models/crmModel';
import { Request, Response } from 'express';

const Contact = mongoose.model('Contact', ContactSchema);
export class ContactController{
...
public addNewContact (req: Request, res: Response) {                
        let newContact = new Contact(req.body);
    
        newContact.save((err, contact) => {
            if(err){
                res.send(err);
            }    
            res.json(contact);
        });
    }

我建议你查看此友好的TypeScript教程。

总结

Node令人印象深刻, 但并非没有(很多?)问题。也就是说, 这适用于现有的所有新技术和新技术, 我们会更好地理解Node并与其一起使用。

我希望这五个技巧可以防止你陷入长期存在的错误和性能问题的困境中。如果我错过了一些有趣的事情, 请告诉我, 我很高兴(实际上, 非常感谢!)将它们包括在文章中。 ????

赞(0)
未经允许不得转载:srcmini » Node开发人员犯的5大错误

评论 抢沙发

评论前必须登录!