我在nodejs中尝试了这段代码:
var fs = require('fs-extra');
console.log("-- line 1 --");
fs.ensureDir('./abc', function (err) {
if (!err) console.log("-- ensured --");
});
fs.copy("./sample", "./myFolder/samps", function (err) {
if (err) return console.error("sample to myFolder failed"); // sample is a file
console.log("-- copied --");
});
fs.readdir("./myFolder", function (err, files) {
if (err) return console.error("-- read my dir --");
files.forEach( function (file) {
console.log(file);
});
console.log("-- my folder done --");
});
console.log("-- line 2 --");
我得到的输出是:
-- line 1 --
-- line 2 --
....
list of files -> doesn't include the newly copied "samps" file
....
-- my folder done --
-- ensured --
-- copied --
现在我的问题是,回调执行的顺序不应该是我编写它们的顺序 - 也就是说,不应该是这样 - 确保,复制,文件列表和myFolder完成了?
现在下一个让我感到困惑的是
var fs = require('fs-extra');
console.log("-- line 1 --");
fs.ensureDir('./abc', function (err) {
if (!err) console.log("-- ensured --");
});
fs.copy("./sample", "./myFolder/samps", function (err) {
if (err) return console.error("sample to myFolder failed"); // sample is a file
console.log("-- copied --");
});
fs.readdir("./", function (err, files) {
if (err) return console.error("-- read root dir --");
files.forEach( function (file) {
console.log(file);
});
console.log("-- root dir done --");
});
console.log("-- line 2 --");
输出:
-- line 1 --
-- line 2 --
-- ensured --
....
list of files and directories -> includes the newly created "abc" directory
....
-- root dir done --
-- copied --
我不明白在文件列表之前是如何打印确保,但在前一种情况下不是,为什么已复制总是在最后打印出来?
如何在列表中创建 abc ,但 samps 是否包含在上一个中?
有人可以解释一下这种行为吗?
答案 0 :(得分:1)
文件系统请求(不是来自具有'同步'后缀的方法)在线程池中执行,因此所有3个请求将并行执行。因此,由于各种因素(例如磁盘状态,操作系统调度等),您无法对这些请求的完成顺序做出任何假设。
如果您需要确保订单,则需要使用第三方async
模块,Promises等链接请求。
答案 1 :(得分:1)
Look nodejs是一种异步语言,它永远不会在其单个主线程上等待任何输入输出。
因此,在代码中执行行的顺序将类似于下面提到的顺序。 1,2,3,4,5。 随着2,3,4的执行,将在nodejs中注册回调,这将在收到相应功能的响应时执行。现在功能响应的顺序可能取决于多个因素(CPU使用率,磁盘可用性等),并且将取决于执行该操作所需的执行时间。
1. console.log("-- line 1 --");
2. fs.ensureDir('./abc', function (err) {
if (!err) console.log("-- ensured --");
});
3. fs.copy("./sample", "./myFolder/samps", function (err) {
if (err) return console.error("sample to myFolder failed"); // sample is a file
console.log("-- copied --");
});
4. fs.readdir("./myFolder", function (err, files) {
if (err) return console.error("-- read my dir --");
files.forEach( function (file) {
console.log(file);
});
console.log("-- my folder done --");
});
5. console.log("-- line 2 --");
答案 2 :(得分:0)
fs-extra 模块,就像核心 fs 模块一样提供两种功能
在同步的情况下,执行线程会阻塞,直到函数完成,然后才能进行下一次调用。因此,函数将被执行并完成它们被调用的顺序。 在异步情况下,无法控制它们完成执行的顺序并触发回调以登录到控制台。
您正在使用函数的异步,非阻塞版本。因此,订单不会被保留。
的文档答案 3 :(得分:0)
您对fs
的调用已将执行放入池中。您无权访问该池,也无法知道它将如何以及何时执行它。
这是怎么回事:
| Node.js thread | Pool |
| ----------------------------- | --------------------------------- |
| import fs | |
| Print "-- line 1 --" | |
| Start fs.ensureDir | fs.ensureDir |
| Start fs.copy | fs.ensureDir, fs.copy |
| Start fs.readdir | fs.ensureDir, fs.copy, fs.readdir |
| Print "-- line 2 --" | fs.ensureDir, fs.copy, fs.readdir |
| | fs.copy, fs.readdir |
| Print "-- ensured --" | fs.copy, fs.readdir |
| | fs.copy |
| Print "-- copied --" | fs.copy |
| | |
| Print "-- root dir done --" | |
如果您希望按照预期的顺序进行调用,则必须告诉node.js等待fs
执行结束,然后才能继续:
var fs = require('fs-extra');
console.log('-- line 1 --');
fs.ensureDir('./abc', function (err) {
if (!err) console.log('-- ensured --');
fs.copy('./sample', './myFolder/samps', function (err) {
if (err) return console.error('sample to myFolder failed'); // sample is a file
console.log('-- copied --');
fs.readdir('./', function (err, files) {
if (err) return console.error('-- read root dir --');
files.forEach( function (file) {
console.log(file);
});
console.log('-- root dir done --');
console.log('-- line 2 --');
});
});
});
或者:
'use strict';
var async = require('async'),
fs = require('fs-extra');
async.series([
(callback) => {
console.log('-- line 1 --');
callback();
},
(callback) => {
fs.ensureDir('./abc', function (err) {
if (!err) console.log('-- ensured --');
callback();
});
},
(callback) => {
fs.copy('./sample', './myFolder/samps', function (err) {
if (err) {
callback('sample to myFolder failed');
}
console.log('-- copied --');
callback();
});
},
(callback) => {
fs.readdir('./', function (err, files) {
if (err) {
callback('-- read root dir --');
}
files.forEach( function (file) {
console.log(file);
});
console.log('-- root dir done --');
});
}
], (error) => {
if(error) {
console.error(error);
}
console.log('-- line 2 --');
});