我有3层这样的回调:
app.post('/', (req, res) => {
var filename = `outputs/${Date.now()}_output.json`;
let trainInput = req.files.trainInput;
let trainOutput = req.files.trainInput;
let testInput = req.files.trainInput;
//first
trainInput.mv(`inputs/${req.body.caseName}/train_input.csv`, function (err) {
if (err) return res.status(500).send(err);
//second
trainOutput.mv(`inputs/${req.body.caseName}/train_output.csv`, function (err) {
if (err) return res.status(500).send(err);
//third
testInput.mv(`inputs/${req.body.caseName}/test_input.csv`, function (err) {
if (err) return res.status(500).send(err);
res.send('success');
});
});
});
});
在这种情况下,仅上传3个文件。在另一种情况下,我上传的文件超过10个,它进行了10层回调。我知道这是因为JavaScript是异步的。
在这种情况下,有什么办法可以编写漂亮的代码?这是因为当它进行10层回调时,代码在水平上看起来很奇怪。
谢谢
答案 0 :(得分:6)
您可以使用以下代码使您的代码看起来更好并避免回调地狱
app.post('/', async (req, res) => {
var filename = `outputs/${Date.now()}_output.json`;
let trainInput = req.files.trainInput;
let trainOutput = req.files.trainInput;
let testInput = req.files.trainInput;
try {
var result1 = await trainInput.mv(`inputs/${req.body.caseName}/train_input.csv`);
var result2 = await trainInput.mv(`inputs/${req.body.caseName}/train_output.csv`);
var result2 = await testInput.mv(`inputs/${req.body.caseName}/test_input.csv`);
res.send('success');
}
catch (error) {
res.status(500).send(error);
}
});
答案 1 :(得分:3)
您可以使函数返回Promise
我建议您执行一项功能,因为您执行相同的操作3次。在这种情况下,我将函数称为“保存”,但您可以随意调用它。第一个参数是文件末尾,第二个参数是输出文件名。
function save(file, output) = return new Promise((resolve, reject) => {
file.mv(`inputs/${req.body.caseName}/${output}`, err =>
if (err) return reject(err)
resolve()
})
Promise.all([
save(req.files.trainInput, 'train_input.csv'),
save(req.files.trainInput, 'train_output.csv'),
save(req.files.trainInput, 'test_input.csv')
])
.then(_ => res.send(200))
.catch(err => res.send(400);
答案 2 :(得分:0)
您使用的是哪个版本的Node?如果异步/等待可用,则将其清理一堆。
const moveCsv = (file, dest) => {
return new Promise((resolve, reject) => {
//third
file.mv(dest, function (err) {
if (err) reject(err);
resolve();
});
})
}
app.post('/', async(req, res) => {
try {
var filename = `outputs/${Date.now()}_output.json`;
const {
trainInput,
trainOutput,
testInput
} = req.files;
const prefix = `inputs/${req.body.caseName}`;
await moveCsv(trainInput, `${prefix}/train_input.csv`);
await moveCsv(trainOutput, `${prefix}/train_output.csv`);
await moveCsv(testInput, `${prefix}/test_input.csv`);
res.send('success');
} catch(err) {
res.status(500).send(err);
}
});
我在这里还假设您的trainInput
,trainOutput
,testOutput
并非全部都是req.files.trainInput
。
请小心,因为await
调用的同步性质是线程阻塞。如果那个writer函数需要很长时间,您还可以考虑将这些调用放在工作线程上。您对该服务器端点的请求是否快速且不频繁并不重要。
答案 3 :(得分:0)
您可以将 RXJS 添加到项目中,并使用 Observables.forkJoin()
可观察物的解决方案( assuming that trainInput.mv() returns Observable ):
/* Without a selector */
var source = Rx.Observable.forkJoin(
trainInput.mv(`inputs/${req.body.caseName}/train_input.csv`),
trainInput.mv(`inputs/${req.body.caseName}/train_output.csv`),
trainInput.mv(`inputs/${req.body.caseName}/test_input.csv`)
);
var subscription = source.subscribe(
function (x) {
// On success callback
console.log('Success: %s', x);
},
function (err) {
// Error callback
console.log('Error');
},
function () {
// Completed - runs always
console.log('Completed');
});
// => Success: [result_1, result_2, result_3] or Error
// => Completed