Si vous effectuez cette opération au démarrage ou à l'initialisation de l'application, il est très bien de bloquer l'exécution car vous feriez la même chose si vous le faisiez en mode asynchrone. Si vous créez un répertoire comme une opération récurrente, sa mauvaise pratique, mais ne causera probablement aucun problème de performances, mais c'est néanmoins un mauvais habbit. À utiliser uniquement pour démarrer votre application ou autrement pour des opérations ponctuelles.
utiliser les Syncméthodes * est généralement un non-non: ne pas vouloir bloquer la boucle d'événements
Max Heiber
14
L'utilisation de méthodes de synchronisation est très bien pour les scripts locaux et autres, ce n'est évidemment pas une bonne idée pour un serveur.
Pier
Si ce bloc est entouré de setTimeout, c'est async .....................
Bryan Grace
186
Non, pour plusieurs raisons.
Le pathmodule n'a pas de méthode exists/ existsSync. C'est dans le fsmodule. (Peut-être que vous venez de faire une faute de frappe dans votre question?)
fs.exists()est un anachronisme et n'existe que pour des raisons historiques. Il ne devrait presque jamais y avoir de raison de l'utiliser dans votre propre code.
En particulier, vérifier si un fichier existe avant de l'ouvrir est un anti-pattern qui vous laisse vulnérable aux conditions de concurrence: un autre processus peut supprimer le fichier entre les appels à fs.exists()et fs.open(). Ouvrez simplement le fichier et gérez l'erreur lorsqu'il n'est pas là.
Puisque nous parlons d'un répertoire plutôt que d'un fichier, ce conseil implique que vous devez simplement appeler mkdiret ignorer inconditionnellement EEXIST.
En général, vous devez éviter les Syncméthodes * . Ils bloquent, ce qui signifie que rien d'autre dans votre programme ne peut se produire pendant que vous allez sur le disque. Il s'agit d'une opération très coûteuse, et le temps qu'il faut brise l'hypothèse de base de la boucle d'événements du nœud.
Les Syncméthodes * sont généralement bien dans les scripts rapides à usage unique (ceux qui font une chose puis se terminent), mais ne devraient presque jamais être utilisés lorsque vous écrivez un serveur: votre serveur ne pourra répondre à personne pendant toute la durée des demandes d'E / S. Si plusieurs demandes client nécessitent des opérations d'E / S, votre serveur s'arrêtera très rapidement.
La seule fois où j'envisagerais d'utiliser les Syncméthodes * dans une application serveur est une opération qui se produit une fois (et une seule fois), au démarrage. Par exemple, requireutilise réellementreadFileSync pour charger des modules.
Même dans ce cas, vous devez toujours être prudent car de nombreuses E / S synchrones peuvent ralentir inutilement le temps de démarrage de votre serveur.
Au lieu de cela, vous devez utiliser les méthodes d'E / S asynchrones.
Donc, si nous rassemblons ces conseils, nous obtenons quelque chose comme ceci:
function ensureExists(path, mask, cb){if(typeof mask =='function'){// allow the `mask` parameter to be optional
cb = mask;
mask =0777;}
fs.mkdir(path, mask,function(err){if(err){if(err.code =='EEXIST') cb(null);// ignore the error if the folder already existselse cb(err);// something else went wrong}else cb(null);// successfully created folder});}
Et nous pouvons l'utiliser comme ceci:
ensureExists(__dirname +'/upload',0744,function(err){if(err)// handle folder creation errorelse// we're all good});
Bien sûr, cela ne tient pas compte des cas marginaux comme
Que se passe-t-il si le dossier est supprimé pendant l'exécution de votre programme? (en supposant que vous vérifiez seulement qu'il existe une fois au démarrage)
Que se passe-t-il si le dossier existe déjà mais avec les mauvaises autorisations?
ce drapeau "masque" est-il toujours d'actualité en 2019? quel en était le but?
oldboy
C'est le mode de fichier Unix - les autorisations de lecture / écriture du répertoire.
josh3736
44
J'ai trouvé et module npm qui fonctionne comme un charme pour cela. Il suffit de faire un mkdir récursivement lorsque cela est nécessaire, comme un "mkdir -p".
// Creates /tmp/a/apple, regardless of whether `/tmp` and /tmp/a exist.
fs.mkdir('/tmp/a/apple',{ recursive:true},(err)=>{if(err)throw err;});
REMARQUE: vous devez d'abord importer le fsmodule intégré.
Voici maintenant un exemple un peu plus robuste qui exploite les modules ES natifs (avec indicateur activé et extension .mjs), gère les chemins non root et prend en compte les chemins d'accès complets:
import fs from'fs';import path from'path';
createDirectories(pathname){const __dirname = path.resolve();
pathname = pathname.replace(/^\.*\/|\/?[^\/]+\.[a-z]+|\/$/g,'');// Remove leading directory markers, and remove ending /file-name.extension
fs.mkdir(path.resolve(__dirname, pathname),{ recursive:true}, e =>{if(e){
console.error(e);}else{
console.log('Success');}});}
Vous pouvez l'utiliser comme createDirectories('/components/widget/widget.js');.
Et bien sûr, vous voudrez probablement devenir plus sophistiqué en utilisant des promesses avec async / wait pour tirer parti de la création de fichiers de manière synchrone plus lisible lorsque les répertoires sont créés; mais, cela dépasse la portée de la question.
pour l'approche prometteuse n ° 1, vous pouvez réorganiser la capture. mkdir('/path').catch(err => { if (err.code != 'EEXIST') throw err;}).then(myFunc);
Une telle réponse sous-estimée! fs-extra a bacame un must have pour moi. Je pense que c'est une abréviation d'écrire 10+ lignes juste pour vérifier si un dossier existe ...
538ROMEO
10
La meilleure solution serait d'utiliser le module npm appelé node-fs-extra . Il a une méthode appelée mkdirqui crée le répertoire que vous avez mentionné. Si vous donnez un long chemin de répertoire, il créera automatiquement les dossiers parents. Le module est un super ensemble de modules npm fs, vous pouvez donc utiliser toutes les fonctions fségalement si vous ajoutez ce module.
Pour Node.js v7.4.0, la documentation indique qu'elle fs.exists()est obsolète, mais fs.existsSync()ne l'est pas. Pourriez-vous ajouter un lien vers une ressource disant qui fs.existsSync()est dépréciée?
francis
1
Les réponses uniquement codées ne sont pas très utiles aux utilisateurs qui viendront à cette question à l'avenir. Veuillez modifier votre réponse pour expliquer pourquoi votre code résout le problème d'origine
Merci! Il semble que la fonction existait dans la version 0.12, s'est déconseillée dans les versions 4 et 5 et a été restaurée dans les versions 6 et 7 ... Une sorte de fonction zombi ...
var filessystem = require('fs');var dir ='./path/subpath/';if(!filessystem.existsSync(dir)){
filessystem.mkdirSync(dir);}else{
console.log("Directory already exist");}
const fs = require('fs')// in javascriptimport* as fs from"fs"// in typescriptimport fs from"fs"// in typescript// it will create the directory if it does not exist.!fs.existsSync(`./assets/`)&& fs.mkdirSync(`./assets/`,{ recursive:true})
Il fait la même chose et a les mêmes cas de bord, il se trouve qu'il utilise juste des promesses, des typedefs dactylographiés et fonctionne avec "use strict".
// https://en.wikipedia.org/wiki/File_system_permissions#Numeric_notationconst allRWEPermissions = parseInt("0777",8);function ensureFilePathExists(path: string, mask: number = allRWEPermissions):Promise<void>{returnnewPromise<void>(function(resolve:(value?:void|PromiseLike<void>)=>void,
reject:(reason?: any)=>void):void{
mkdir(path, mask,function(err:NodeJS.ErrnoException):void{if(err){if(err.code ==="EEXIST"){
resolve(null);// ignore the error if the folder already exists}else{
reject(err);// something else went wrong}}else{
resolve(null);// successfully created folder}});});}
import path from'path';import fs from'fs';(async()=>{const dir = path.join(__dirname,'upload');try{await fs.promises.mkdir(dir);}catch(error){if(error.code ==='EEXIST'){// Something already exists, but is it a file or directory?const lstat =await fs.promises.lstat(dir);if(!lstat.isDirectory()){throw error;}}else{throw error;}}})();
Vous pouvez utiliser la commande noeud File System fs.stat pour vérifier si dir existe et fs.mkdir pour créer un répertoire avec rappel, ou fs.mkdirSync pour créer un répertoire sans rappel, comme cet exemple:
//first require fsconst fs = require('fs');// Create directory if not exist (function)const createDir =(path)=>{// check if dir exist
fs.stat(path,(err, stats)=>{if(stats.isDirectory()){// do nothing}else{// if the given path is not a directory, create a directory
fs.mkdirSync(path);}});};
Voici une petite fonction pour créer récursivement des répertoires:
const createDir =(dir)=>{// This will create a dir given a path such as './folder/subfolder' const splitPath = dir.split('/');
splitPath.reduce((path, subPath)=>{let currentPath;if(subPath !='.'){
currentPath = path +'/'+ subPath;if(!fs.existsSync(currentPath)){
fs.mkdirSync(currentPath);}}else{
currentPath = subPath;}return currentPath
},'')}
Réponses:
la source
Sync
méthodes * est généralement un non-non: ne pas vouloir bloquer la boucle d'événementsNon, pour plusieurs raisons.
Le
path
module n'a pas de méthodeexists
/existsSync
. C'est dans lefs
module. (Peut-être que vous venez de faire une faute de frappe dans votre question?)Les documents vous découragent explicitement d'utiliser
exists
.Puisque nous parlons d'un répertoire plutôt que d'un fichier, ce conseil implique que vous devez simplement appeler
mkdir
et ignorer inconditionnellementEEXIST
.En général, vous devez éviter les
Sync
méthodes * . Ils bloquent, ce qui signifie que rien d'autre dans votre programme ne peut se produire pendant que vous allez sur le disque. Il s'agit d'une opération très coûteuse, et le temps qu'il faut brise l'hypothèse de base de la boucle d'événements du nœud.Les
Sync
méthodes * sont généralement bien dans les scripts rapides à usage unique (ceux qui font une chose puis se terminent), mais ne devraient presque jamais être utilisés lorsque vous écrivez un serveur: votre serveur ne pourra répondre à personne pendant toute la durée des demandes d'E / S. Si plusieurs demandes client nécessitent des opérations d'E / S, votre serveur s'arrêtera très rapidement.La seule fois où j'envisagerais d'utiliser les
Sync
méthodes * dans une application serveur est une opération qui se produit une fois (et une seule fois), au démarrage. Par exemple,require
utilise réellementreadFileSync
pour charger des modules.Même dans ce cas, vous devez toujours être prudent car de nombreuses E / S synchrones peuvent ralentir inutilement le temps de démarrage de votre serveur.
Au lieu de cela, vous devez utiliser les méthodes d'E / S asynchrones.
Donc, si nous rassemblons ces conseils, nous obtenons quelque chose comme ceci:
Et nous pouvons l'utiliser comme ceci:
Bien sûr, cela ne tient pas compte des cas marginaux comme
la source
0744 == 484
.J'ai trouvé et module npm qui fonctionne comme un charme pour cela. Il suffit de faire un mkdir récursivement lorsque cela est nécessaire, comme un "mkdir -p".
https://www.npmjs.com/package/mkdirp
la source
La
mkdir
méthode a la capacité de créer récursivement tous les répertoires d'un chemin qui n'existent pas et d'ignorer ceux qui existent.Depuis les documents Node v10 / 11 :
REMARQUE: vous devez d'abord importer le
fs
module intégré.Voici maintenant un exemple un peu plus robuste qui exploite les modules ES natifs (avec indicateur activé et extension .mjs), gère les chemins non root et prend en compte les chemins d'accès complets:
Vous pouvez l'utiliser comme
createDirectories('/components/widget/widget.js');
.Et bien sûr, vous voudrez probablement devenir plus sophistiqué en utilisant des promesses avec async / wait pour tirer parti de la création de fichiers de manière synchrone plus lisible lorsque les répertoires sont créés; mais, cela dépasse la portée de la question.
la source
Juste au cas où toute personne intéressée par la version à une ligne. :)
la source
Vous pouvez simplement utiliser
mkdir
et intercepter l'erreur si le dossier existe.C'est asynchrone (donc meilleure pratique) et sûr.
(Ajoutez éventuellement un deuxième argument avec le mode.)
D'autres pensées:
Vous pouvez alors utiliser ou attendre en utilisant natif promisify .
Vous pouvez faire votre propre méthode de promesse, quelque chose comme (non testé):
Pour la vérification synchrone, vous pouvez utiliser:
Ou vous pouvez utiliser une bibliothèque, les deux plus populaires étant
la source
mkdir('/path').catch(err => { if (err.code != 'EEXIST') throw err;}).then(myFunc);
!==
place de!=
Avec le package fs-extra , vous pouvez le faire avec une doublure :
la source
La meilleure solution serait d'utiliser le module npm appelé node-fs-extra . Il a une méthode appelée
mkdir
qui crée le répertoire que vous avez mentionné. Si vous donnez un long chemin de répertoire, il créera automatiquement les dossiers parents. Le module est un super ensemble de modules npmfs
, vous pouvez donc utiliser toutes les fonctionsfs
également si vous ajoutez ce module.la source
la source
fs.exists()
est obsolète, maisfs.existsSync()
ne l'est pas. Pourriez-vous ajouter un lien vers une ressource disant quifs.existsSync()
est dépréciée?Apr 2018
: nodejs.org/api/fs.html#fs_fs_existssync_pathCela peut vous aider :)
la source
Solution
la source
Je voudrais ajouter un refactoriseur Typescript Promise de la réponse de josh3736 .
Il fait la même chose et a les mêmes cas de bord, il se trouve qu'il utilise juste des promesses, des typedefs dactylographiés et fonctionne avec "use strict".
la source
Avec Node 10 + ES6:
la source
Vous pouvez utiliser la commande noeud File System fs.stat pour vérifier si dir existe et fs.mkdir pour créer un répertoire avec rappel, ou fs.mkdirSync pour créer un répertoire sans rappel, comme cet exemple:
la source
Voici une petite fonction pour créer récursivement des répertoires:
la source
Utiliser async / wait:
Vous devrez promettre
fs
:la source