NodeJS中有多个writeFile(Multiple writeFile in NodeJS)
我有一个任务是将部分数据写入单独的文件中:
fs.writeFile('content/a.json', JSON.stringify(content.a, null, 4), function(err) { if(err) { console.log(err); } else { console.log('a.json was updated.'); } }); fs.writeFile('content/b.json', JSON.stringify(content.b, null, 4), function(err) { if(err) { console.log(err); } else { console.log('b.json was updated.'); } }); fs.writeFile('content/c.json', JSON.stringify(content.c, null, 4), function(err) { if(err) { console.log(err); } else { console.log('c.json was updated.'); } }); fs.writeFile('content/d.json', JSON.stringify(content.d, null, 4), function(err) { if(err) { console.log(err); } else { console.log('d.json was updated.'); } });
但是现在我有4种不同的回调,所以当4个任务完成时我无法得到这个时刻。 是否可以并行执行4个writeFile调用并获取1个回调,这将在创建4个文件时调用?
PS
当然,我可以这样做:
fs.writeFile('a.json', data, function(err) { fs.writeFile('b.json', data, function(err) { .... callback(); } }
只是好奇有没有其他的方式来做到这一点。 谢谢。
I have a task to write parts of the data to separate files:
fs.writeFile('content/a.json', JSON.stringify(content.a, null, 4), function(err) { if(err) { console.log(err); } else { console.log('a.json was updated.'); } }); fs.writeFile('content/b.json', JSON.stringify(content.b, null, 4), function(err) { if(err) { console.log(err); } else { console.log('b.json was updated.'); } }); fs.writeFile('content/c.json', JSON.stringify(content.c, null, 4), function(err) { if(err) { console.log(err); } else { console.log('c.json was updated.'); } }); fs.writeFile('content/d.json', JSON.stringify(content.d, null, 4), function(err) { if(err) { console.log(err); } else { console.log('d.json was updated.'); } });
But now I have 4 different callbacks, so I can't get the moment, when all 4 task have been finished. Is it possible to parallel 4 writeFile calls and get only 1 callback, which will be called when 4 files was created?
P.S.
Of course I can do smth like:
fs.writeFile('a.json', data, function(err) { fs.writeFile('b.json', data, function(err) { .... callback(); } }
Just curious is there any other way to do this. Thanks.
原文:https://stackoverflow.com/questions/26413329
最满意答案
您确实可以将对象“转换”为特定类型。
object stringAsObject = "This is a string"; string stringAsString = (string)stringAsObject;
但在这种情况下,我建议使用泛型。 在某些情况下,创建泛型方法可能有点复杂 - 幸运的是我不相信这是其中之一。
使用泛型,您不必将所有内容更改为“对象”,编译器可以为您跟踪类型。 这将允许它显示您的代码中的许多错误。
为了给你一个起点,我尝试在这里将对象池类更改为通用实现。 我为我改变的事情和你仍然需要处理的事情添加了评论。 注意我没有运行它,只是检查了Visual Studio中没有突出显示的错误,因此一旦开始调试,可能仍需要更改一些内容。 :)
// Changed to Generics. This makes the class easier to use. public class PoolOfObjects<T> { // Changed to private - you do not want this accessible from the outside // Changed the type to T so you do not have to cast. private T[] _objects; // Changed to prefix with _. // Not all coding guidelines do this, but whatever you do be consistent. // Changed to states as there appears to be on per object. private bool?[] _states; // Using the standard Func<T> (function returning T) // instead of introducing a new delegate type private Func<T> _creator; // Changed to camelCase and Func<T> instead of custom delegate public PoolOfObjects(int objectsCount, Func<T> creator) { // Changed to remember the creator _creator = creator; // I left this an array, but consider changing to List<T>, // then the list can grow as needed. _objects = new T[objectsCount]; _states = new bool?[objectsCount]; // removed initialization of objects // as it appears you do it when calling EjectObject } //Must return an exemplar by state of object when called public T EjectObject(bool? state) { // TODO: // You never assign any values to the _states array, // so it will always have the value null. // this means if your method is called with true or false, // it will FAIL! // I do not know what "states" is for so I can't suggest how to fix it. // If it is to track if an object is already in use I recommend getting // rid of it and change your _objects to be: // private Queue<T> _objects // Then this method will check if there are any items in the _objects queue, // if there is dequeue one and return it. If not, create a new object // and return it. // You then need to create another method to put the items back in the queue // after use. int i; for (i = 0; i < _states.Length; i++) if (_states[i] == state) { //create object if null if (_objects[i] == null) // Changed to call your creator instead of assigning it. _objects[i] = _creator(); break; } // TODO: Your program will crash with an unclear error here if no object // has a state matching the requested state. return _objects[i]; } }
You can indeed "Cast" your object to a specific type.
object stringAsObject = "This is a string"; string stringAsString = (string)stringAsObject;
But in this case I would recommend using Generics. Creating generic methods can be a bit complex in some cases - luckily I do not believe this is one of them.
With generics you do not have to change everything to an "object" and the compiler can keep track of the types for you. This will allow it to show a number of errors you have in your code.
To give you a starting point to work from, I have tried changing your object pool class into a generic implementation here. I added comments for things I changed and things you still need to work on. Notice I did not run this, just checked no error is highlighted in Visual Studio, so there might still be a few things you need to change once you start debugging. :)
// Changed to Generics. This makes the class easier to use. public class PoolOfObjects<T> { // Changed to private - you do not want this accessible from the outside // Changed the type to T so you do not have to cast. private T[] _objects; // Changed to prefix with _. // Not all coding guidelines do this, but whatever you do be consistent. // Changed to states as there appears to be on per object. private bool?[] _states; // Using the standard Func<T> (function returning T) // instead of introducing a new delegate type private Func<T> _creator; // Changed to camelCase and Func<T> instead of custom delegate public PoolOfObjects(int objectsCount, Func<T> creator) { // Changed to remember the creator _creator = creator; // I left this an array, but consider changing to List<T>, // then the list can grow as needed. _objects = new T[objectsCount]; _states = new bool?[objectsCount]; // removed initialization of objects // as it appears you do it when calling EjectObject } //Must return an exemplar by state of object when called public T EjectObject(bool? state) { // TODO: // You never assign any values to the _states array, // so it will always have the value null. // this means if your method is called with true or false, // it will FAIL! // I do not know what "states" is for so I can't suggest how to fix it. // If it is to track if an object is already in use I recommend getting // rid of it and change your _objects to be: // private Queue<T> _objects // Then this method will check if there are any items in the _objects queue, // if there is dequeue one and return it. If not, create a new object // and return it. // You then need to create another method to put the items back in the queue // after use. int i; for (i = 0; i < _states.Length; i++) if (_states[i] == state) { //create object if null if (_objects[i] == null) // Changed to call your creator instead of assigning it. _objects[i] = _creator(); break; } // TODO: Your program will crash with an unclear error here if no object // has a state matching the requested state. return _objects[i]; } }
相关问答
更多-
我刚才有这个确切的问题。 我有一个视图控制器使用AQRecorder类从AQRecorder.mm。 当我在视图控制器中包含AQRecorder.h时,会发生这些错误。 在我看来,因为我的直观目标c视图控制器(命名为.m文件)包括编译器抛出虚假错误的C ++头文件。 有两个解决方案。 最快的是将视图控制器类(包括AQRecorder.h)重命名为.mm文件,在我的情况下将UIRecorderViewController从.m更改为.mm。 或者,移动以下内容包括: #include "CAStreamBas ...
-
“获取实现的方法似乎返回实例变体,我无法让它们在静态类本身上启动。” 然后使用objc_getMetaClass("ClassName")而不是objc_getClass 。 类对象本身就是对象,是其元类的实例。 如果将metaclass对象传递给例如class_getMethod() ,一切都会好的。 "Methods for getting implementations seem to return instance variants and I can't get them to fire on t ...
-
然后你需要使用反射来获取方法并调用它。 如果要声明该类型的对象,则需要在编译时解析泛型类型参数: Type t= GetTypeAtRuntime();; var doSomething = typeof(List<>).MakeGenericType(t).GetMethod("DoSomething", BindingFlags.Static | BindingFlags.Public); doSomething.Invoke(null, new object[] { }); 但是在您的示例中,T未在 ...
-
如何将具有未知类型的对象传递给具有未知类型的类(How to pass an object with an unknown type to a Class with an unknown type)[2019-12-31]
使用的方法是Object.equals(Object) 。 您可以迭代集合fc并检查它是否包含equals(o)的元素。 如果是这样,继续使用所述元素(类型为T )。 for(T e : fc) { if(o.equals(e)) { // carry on with e } } 您可能还想覆盖o == null 。 The method to use is Object.equals(Object). You can iterate the collection fc a ... -
您已将instrumentList[]声明为Strings数组。 您的for循环尝试在这些Strings上调用以下方法: InstrumentNameDisplay() NumberOfStrings(String) TuneInstrument() `PlayInstrument() PlayInstrumentBand() StopPlayInstrument() 这些都不是String类的方法。 看起来你可能要做的就是建立一个Instruments阵列...... You've declared in ...
-
您确实可以将对象“转换”为特定类型。 object stringAsObject = "This is a string"; string stringAsString = (string)stringAsObject; 但在这种情况下,我建议使用泛型。 在某些情况下,创建泛型方法可能有点复杂 - 幸运的是我不相信这是其中之一。 使用泛型,您不必将所有内容更改为“对象”,编译器可以为您跟踪类型。 这将允许它显示您的代码中的许多错误。 为了给你一个起点,我尝试在这里将对象池类更改为通用实现。 我为我改变的事 ...
-
就我个人而言,我发现任何数量的静态方法都是麻烦的迹象。 如果你的类有实例方法和静态方法,那么很可能你可以将这个类分成两个独立的实体,并将静态方法改为实例方法。 将一个阶级想象成一种特殊的对象,具有独特的属性,它具有全球性。 由于它是一个全局变量,它意味着非常强大的耦合级别,因此您希望减少对它的任何引用。 静态成员将需要被引用,这意味着你的代码将获得与班级的强烈联系。 Personally I find that any number of static methods are a sign of troub ...
-
该方法未附加到原型,因为此对象成为使用Object.create附加到新创建的对象的原型。 而且你不需要原型的原型。 请记住, Object.create不会深度克隆对象。 相反,它等同于 Object.create = function(proto) { function F() {} F.prototype = proto; return new F(); } (实际实现更复杂,但这个简短的版本说明了这个想法) 所有新创建的对象都从作为原型的foo “继承”方法,这里没有重复。 ...
-
因为你正在检查!= NULL我想你有一个指针数组。 使用指针数组,您的代码可以工作,因为您知道指针的大小,即使它是一个void指针。 如果我的假设是正确的,你可以这样编码: int nb_elems(void** array) { void** end = array; while(*end != NULL) { end++; } return end - array; } 但此代码仅适用于指针指针或指针数组。 用法: int** iptrs = (int* ...
-
未知类型名称'class'(unknown type name 'class')[2023-05-17]
实际上,Atom似乎自动检测到一个.h头文件作为C语言文件。 这里解释了几种解决方法。 我试着用ctrl + shift + L手动切换C到C ++,现在我没有任何错误了。 我可能在单词class旁边仍然有一个红点,并显示这样的错误: expected ';' after top level declarator 但代码正常运行。 Actually, seems that Atom detects a .h header file as a C-language file automatically. S ...