将Promise.all()与SequeliseJS一起使用



我想检查我的数据库中是否使用了上传文件。所以我想列出";上传";文件夹,然后与SequelizeJs检查项目是否找到了正确的属性。

我的代码似乎没有按预期工作:

var promises = [];
fs.readdir('./public/uploads', (err, files) => {
if (!err) {
promises = files.filter(function(file) {
if (file !== 'csv' && file !== '.gitignore') {
// vérification dans FileModel
return models.FileModel.findOne({ where: { name: '/uploads/' + file } }).then(function(findedFile) {
if (!findedFile) {
return Promise.resolve(file).then(function() {
// Vérification dans VehiclePhotoModel
return models.VehiclePhotoModel.findOne({ where: { name: '/uploads/' + file } }).then(function(findedFile) {
if (!findedFile) {
return Promise.resolve(file);
}
});
});
}
});
}
});
}
});
Promise.all(promises).then(function(unusedFiles) {
response.render('file/_checkUnusedFiles', {
_layoutFile: false,
unusedFiles: unusedFiles
});
});

编辑#1:

我把你的代码弄混了,这对我来说不起作用,但我仍然遇到了一个问题,Promise.resolve((没有返回字符串名称文件。

const fileModels = [
{ model: models.FileModel, property: 'name' },
{ model: models.VehiclePhotoModel, property: 'name' }
];
function _checkUnusedFiles(request, response) {
var promises = [],
files = _.remove(fs.readdirSync('./public/uploads'), function(file) {
return file !== 'csv' && file !== '.gitignore';
});
promises = _.map(files, function(file) {
return fileModels.map(function(fileModel) {
var where = {};
where[fileModel.property] = file;
return fileModel.model.findOne({ where: where }).then(function(findedItem) {
if (!findedItem) {
return Promise.resolve(file);
}
});
});
});
Promise.all(promises).then(function(unusedFiles) {
response.render('optimizer/_checkUnusedFiles', {
_layoutFile: false,
unusedFiles: unusedFiles
});
});
}

使用上面的代码,您很快就会进入回调地狱,这将导致类似您提到的问题。无论如何,问题如下

files.filter返回

<string[]>|<缓冲区[]>|<fs。Dirent[]>

摘自文档:https://nodejs.org/api/fs.html#fs_fs_readdir_path_options_callback

一个更好的方法是循环,然后做一些类似promises.append(...)的事情

更好的方法是使用asyncawait分解代码,以避免回调地狱和类似的问题

在您的情况下,您真的不需要Promise.all,因为它可能会使事情变得更加复杂,并可能成为性能瓶颈。

像这样的东西应该可以正常工作

const fs = require('fs')
const path = require('path')
// Mocking SequeliseJS (You can remove this and replace in code as well with original models
const modelsMock = {
FileModel: {
findOne: (query) => {
return new Promise((resolve, reject) => {
// rand will just randomize result between true and false
let rand = Math.floor(Math.random() * Math.floor(2))
resolve(rand == 1 ? resolve(true) : resolve(false))
})
}
},
VehiclePhotoModel: {
findOne: (query) => {
return new Promise((resolve, reject) => {
// rand will just randomize result between true and false
let rand = Math.floor(Math.random() * Math.floor(2))
resolve(rand == 1 ? resolve(true) : resolve(false))
})
}
}  
}
run()
async function run() {
let promises = []
let existFiles = []
let doesntExistFiles = []
// If the goal is to use readdir async then uncomment the following and comment let files = fs.readdirSync('./public/uploads')
/* 
const util = require('util')
const readdir = util.promisify(fs.readdir);
let files = await readdir('./public/uploads')
*/
let files = fs.readdirSync('./public/uploads')

// Filter files: (using array.filter is pretty useless to us here since we can't run it async unless we want to promisify it which there are plenty of examples out there, for now we will stick with good old fashion loop)
for(var i = 0; i < files.length; i++) {
const file = files[i]
if(path.extname(file) !== '.csv' && path.extname(file) !== '.gitignore') {
try {
let exist = await checkIfFileExist(file, modelsMock)
exist === true ? existFiles.push(file) : doesntExistFiles.push(file)
} catch (e) {
// Handle error here
}
}
}

response.render('file/_checkUnusedFiles', {
_layoutFile: false,
unusedFiles: unusedFiles //Note this will break the code as unusedFiles is undefined, I really dont know what is this variable hence I didn't change it but feel free to change it as you see it appropriate.
});
}
async function checkIfFileExist(file, models){
let query = `{ where: { name: '/uploads/' + ${file} } }`

try {
let existInFiles = await models.FileModel.findOne(query)
if(!existInFiles) {
let existInVehicle = await models.VehiclePhotoModel.findOne(query)
existInVehicle ? return true : return false
} else {
return true
}
}
catch(e) {
throw e
}

}

以下是Repl.it的完整示例

https://repl.it/repls/DramaticAwfulSpreadsheets#index.js

第1版:

就像我在评论中提到的那样,我并没有真正建议你在做什么(至少我的观点是:(;但是,如果您使数组变平,那么一切都会好起来。

const fileModels = [
{ model: models.FileModel, property: 'name' },
{ model: models.VehiclePhotoModel, property: 'name' }
];
function _checkUnusedFiles(request, response) {
var promises = [],
files = _.remove(fs.readdirSync('./public/uploads'), function(file) {
// I think you want to check for extension here and not the file name? if so use this
// return (path.extname(file) !== '.csv' && path.extname(file) !== '.gitignore') //Make sure to require('path')
return file !== 'csv' && file !== '.gitignore';
});
promises = _.map(files, function(file) {
return fileModels.map(function(fileModel) {
var where = {};
// Your query seems wrong? at least different from last time. If it is intentional then you are good otherwise I think you meant to do
//  where[fileModel.property] = `/uploads/${file}`
where[fileModel.property] = file;

return fileModel.model.findOne({ where: where }).then(function(findedItem) {
if (!findedItem) {
return Promise.resolve(file);
}
});
});
});
// Your promises array is more like a 2d array because each file will map to an array of 2 promises 
// So if you flatten it, you should get a 1D promises array
promises = promises.flat()
Promise.all(promises).then(function(unusedFiles) {
response.render('optimizer/_checkUnusedFiles', {
_layoutFile: false,
unusedFiles: unusedFiles
});
});
}

如果你不使promises的输出变平,看起来像下面的

promises = 
[
[ Promise { <pending> }, Promise { <pending> } ],
[ Promise { <pending> }, Promise { <pending> } ]
]

每个条目是一个file,每个model有2个承诺

所以当你做Promise.all(promises)时,它真的不知道如何在2D数组中解释它;然而,当你将其压平时,你的输出看起来类似于:

promises = 
[
Promise { <pending> },
Promise { <pending> },
Promise { <pending> },
Promise { <pending> }
]

现在请记住,unusedFiles的输出可能看起来很奇怪,这是因为并不是每个承诺都会真正解决一些有意义的问题,至少这就是您所映射的。

最新更新