那些年,在Nodejs上踩过的坑(一)

那些年,在Nodejs上踩过的坑(一)

还好,一路踩过来了

13 回复

那些年,在Node.js上踩过的坑(一)

Node.js 是一个非常强大的JavaScript运行时环境,它允许开发者使用JavaScript来编写服务器端的代码。然而,在使用Node.js的过程中,我们可能会遇到一些常见的问题或陷阱,这些问题有时会让我们感到头疼。本文将介绍一些我在使用Node.js过程中遇到的常见问题,并提供一些解决方案。

1. 回调地狱(Callback Hell)

回调函数是Node.js中最常用的一种异步编程模式,但如果不小心处理,很容易导致回调地狱。回调地狱是指嵌套过多的回调函数,使得代码难以阅读和维护。

示例代码:

fs.readFile('file1.txt', function(err, data) {
    if (err) throw err;
    fs.readFile(data.toString(), function(err, data2) {
        if (err) throw err;
        console.log(data2.toString());
    });
});

解决方案: 使用Promise或者async/await来避免回调地狱。

const readFile = filename => new Promise((resolve, reject) => {
    fs.readFile(filename, (err, data) => {
        if (err) reject(err);
        resolve(data);
    });
});

(async () => {
    try {
        const file1Data = await readFile('file1.txt');
        const file2Data = await readFile(file1Data.toString());
        console.log(file2Data.toString());
    } catch (err) {
        console.error(err);
    }
})();

2. 事件循环阻塞

Node.js是一个单线程的运行环境,这意味着所有操作都在同一个线程中执行。如果某个操作耗时较长,会导致整个事件循环阻塞,从而影响其他操作的执行。

示例代码:

// 模拟一个耗时操作
setTimeout(() => {
    console.log("This takes a long time");
}, 5000);

for (let i = 0; i < 1000000000; i++) {
    // 耗时的计算
}
console.log("After the loop");

解决方案: 将耗时的操作放在worker threads或child processes中执行,以避免阻塞主线程。

const { Worker, isMainThread, parentPort } = require('worker_threads');

if (isMainThread) {
    const worker = new Worker(__filename);
    worker.on('message', message => console.log(message));
} else {
    for (let i = 0; i < 1000000000; i++) {
        // 耗时的计算
    }
    parentPort.postMessage("After the loop");
}

通过以上示例,我们可以看到如何避免一些常见的Node.js陷阱。希望这些经验能够帮助你更好地理解和使用Node.js。


  try {
    callback(null, JSON.parse(data.toString()))
  } catch(e) {
    callback(e);
  }

这个应该是callback 本身抛异常了,导致callback被执行两次。。。

最后一个“深度嵌套”的说法不对,你完全没法让JS同步执行的啊,你那篇文章里的“同步执行”只是用一些流程控制的办法或是类库而已。

还有,用Jscex啊Jscex。

try … catch 那个坑哥也干过…

是也乎,是也乎,形式同步,本质异步,表让程序员的头脑生转异步,就是正道,

嗯,之前的说法的确是有问题,我想说的是以下这种情况:

function asyncfun(data, callback) {
  try {
    callback(null, JSON.parse(data.toString()));
  } catch (e) {
    callback(e);
  }
}
var json = {'a': 'b'};
var jsonstr = JSON.stringify(json);
var d = new Buffer(jsonstr);

asyncfun(d, function(err, data) { console.log(err); throw new Error(‘new Error’); })

执行结果:

null
[Error: new Error]

mark 之 学习

哈哈哈哈

好文一枚,顶

好 学习了 那个.on()是什么意思?拼接吗?

好的,以下是一个关于Node.js开发中常见问题及解决方法的帖子,涵盖了一些常见的坑以及如何避免它们。我们将通过一些具体的示例来解释这些问题。

坑1:回调地狱

问题描述: 当异步操作很多时,使用回调函数会导致代码层次嵌套很深,形成所谓的“回调地狱”,代码可读性变差。

解决方案: 使用Promiseasync/await来解决。

// 回调地狱示例
fs.readFile('file1.txt', (err, data) => {
    if (err) throw err;
    console.log(data);
    fs.readFile('file2.txt', (err, data) => {
        if (err) throw err;
        console.log(data);
        // 更多嵌套...
    });
});

// 使用 Promise 解决
const readFile = (filename) => new Promise((resolve, reject) => {
    fs.readFile(filename, (err, data) => {
        if (err) reject(err);
        else resolve(data);
    });
});

readFile('file1.txt')
    .then(data => {
        console.log(data);
        return readFile('file2.txt');
    })
    .then(data => {
        console.log(data);
    })
    .catch(err => {
        console.error(err);
    });

// 使用 async/await 解决
const main = async () => {
    try {
        const data1 = await readFile('file1.txt');
        console.log(data1);
        const data2 = await readFile('file2.txt');
        console.log(data2);
    } catch (err) {
        console.error(err);
    }
};

main();

坑2:同步代码与异步代码混用

问题描述: 当同步代码和异步代码混在一起执行时,可能会导致程序卡死或者逻辑错误。

解决方案: 确保所有可能引起阻塞的操作都使用异步方式处理。

// 错误示例
function processData() {
    let data = fs.readFileSync('data.txt'); // 同步读取文件
    // 进行处理
}

processData();

// 正确示例
function processData() {
    fs.readFile('data.txt', (err, data) => {
        if (err) throw err;
        // 进行处理
    });
}

processData();

总结

以上两个示例展示了Node.js开发中常见的两个坑:回调地狱和同步代码与异步代码混用。通过使用Promiseasync/await,可以有效地解决这些问题,使代码更加简洁、易读和维护。希望这些示例能帮助你在未来的Node.js开发中少踩坑!

回到顶部