Bonjour,
J'ai deux méthodes, une qui retourne l'arborescence d'un dossier _getDirectoryTree
et une autre qui retourne les informations d'un fichier _getFile
. Cette dernière fait un appel à une base de donnée avec Sequelize. Voici la première méthode :
static _getDirectoryTree(url) {
let dir = this._getDirectory(url);
dir.children = {};
const dirData = this._safeReadDirSync(dir.path);
if (dirData !== null) {
dir.children = dirData.map(child => {
const stats = fs.statSync(_path.join(dir.path, child));
if (stats.isDirectory()) {
return this._getDirectory(url + '/' + child);
}
else {
this._getFile(url + '/' + child, stats, (err, file) => {
if (err) return err;
else
return file;
});
}
});
}
console.log('ha');
return dir;
}
Et voici la seconde :
static _getFile(url, stats, cb) {
if (!stats) return undefined;
const path = _path.join(this.root, url);
const path_parsed = _path.parse(path);
db.File.findOne({where: {path: path}, include: ['owner', 'group']})
.then(file => {
file.type = 'file';
file.url = this.url + url;
file.base = path_parsed.base;
file.name = path_parsed.name;
file.ext = path_parsed.ext;
file.size = stats.size;
file.mime = mime.lookup(path_parsed.ext);
console.log('got');
return cb(null, file);
})
.catch(err => {
return cb(err);
});
}
Séparément, les deux méthodes fonctionnent très bien. Mais ensemble, c'est la cata dû au côté asynchrone de Node JS. En effet, j'ai ajouté deux console.log()
dans les méthodes que vous voyez au dessus. Et il se trouve que je vois d'abord ha
et ensuite got
alors que je devrais voir got
puis ha
. Voici le résultat que je souhaiterai obtienir :
{
"type": "directory",
"name": "bar",
"url": "https://192.168.50.5:8080/storage/bar",
"path": "storage/bar",
"children": [
{
"type": "file",
"id": 1,
"path": "storage/bar/foo.txt",
"ownerId": 1,
"groupId": null,
"createdAt": "2017-10-06T00:00:00.000Z",
"updatedAt": "2017-10-06T00:00:00.000Z",
"owner": {
"id": 1,
"username": "groot",
"email": "groot@local.dev",
"password": "$2a$10$qz8OmVUNB4zgf96keFGPWOjM5mb1QhjrbxR.zzz1dtNUadOAlQmBq",
"createdAt": "2017-10-06T14:56:30.000Z",
"updatedAt": "2017-10-06T14:56:30.000Z"
},
"group": null,
"base": "foo.txt",
"name": "foo",
"ext": ".txt",
"size": 0,
"mime": "text/plain"
},
{
"type": "directory",
"name": "fooBar",
"url": "https://192.168.50.5:8080/storage/bar/fooBar",
"path": "storage/bar/fooBar"
},
{
"type": "directory",
"name": "me",
"url": "https://192.168.50.5:8080/storage/bar/me",
"path": "storage/bar/me"
}
]
}
Le fichier du dossier est bien présent. Or moi j'obtient :
{
"type": "directory",
"name": "bar",
"url": "https://192.168.50.5:8080/storage/bar",
"path": "storage/bar",
"children": [
null,
{
"type": "directory",
"name": "fooBar",
"url": "https://192.168.50.5:8080/storage/bar/fooBar",
"path": "storage/bar/fooBar"
},
{
"type": "directory",
"name": "me",
"url": "https://192.168.50.5:8080/storage/bar/me",
"path": "storage/bar/me"
}
]
}
J'ai null à la place de mon fichier parce que Node n'a pas attendu le résultat de _getFile
. Il a retourné l'objet sans. Le truc c'est que je vois mal comment contourner ce problème à l'intérieur d'une fonction map. Est-ce que quelqu'un pourrait m'aider ? Car j'ai une autre méthode _getDirectory
(qui me donne des informations relatives au dossier) qui ne fait pas d'appel à la base de donnée du coup je n'ai pas ce soucis d'attendre non ?
Merci et bonne journée ! :)
utilise les Promise sur ta premiere methode comme ca l'ors de sont appel tu peut utiliser le .then() pour passer la 2eme methode en callback et du coup elle se fera apres la fin de la premiere methode. les Promises rendent le code synchrone en gros.
Comme conseillé, j'ai utilisé les Promise sur mes méthodes. J'obtiens toujours le même soucis sur cette la méthode _getDirectoryTree
(bon ça a résolu pas mal de mes autres problèmes, donc excellent conseil !). Je pense que le soucis vient du fait que j'utilise des Promise embriquées dans une fonction map
. Il faudrait que j'utilise Promise.all()
à mon avis mais j'ai pas réussi à le faire. Voici ce que j'ai pour le moment :
static _getDirectoryTree(url) {
return new Promise(resolve => {
Storage._getDirectory(url)
.then(dir => {
dir.children = {};
Storage._safeReadDir(dir.path)
.then(dirData => {
if (dirData !== null) {
dir.children = dirData.map(child => {
const child_url = url + '/' + child;
Storage._getStats(child_url)
.then(stats => {
if (stats.isDirectory()) {
Storage._getDirectory(child_url)
.then(directory => directory);
}
else {
Storage._getFile(child_url, stats)
.then(file => file);
}
});
});
}
})
.then(() => {
console.log('returning the dir');
return resolve(dir);
});
});
});
};
Dans ma méthode _getDirectory
et _getFile
, j'ai placé les commandes suivantes console.log('Directory ready')
et console.log('File ready')
. Quand je fais ma requête, j'obtient :
Directory ready
returning the dir
Directory ready
Directory ready
File ready
Je vous ai fait un gist avec toute ma classe ici : gist
Merci pour votre aide ! :)