所以,代码可以工作,但是缩进级别是疯了......对于节点中的所有回调,我应该如何编码?
"use strict";
var crypto = require('crypto'),
fs = require('fs'),
mmm = require('mmmagic'),
Magic = require('mmmagic').Magic,
path = require('path');
console.log('Init controller: ' + path.basename(__filename));
exports.help = function () {
var help;
help = "POST http://server/images\n";
help += " Upload image for storage.\n";
help += " <image> - The image file to upload\n";
help += " <title> - The title of the image, no more than 50 characters\n";
help += " <desc> - The description of the image, no more than 1024 characters\n";
return help;
}
exports.post = function (req, res) {
var image = req.files.image;
if (typeof(image) == 'undefined') {
res.status(400).send("{error:'Upload error'}");
return;
}
var magic = new Magic(mmm.MAGIC_MIME_TYPE);
magic.detectFile(image.path, function(err, result) {
if (err) {
res.status(400).send("{error:'Upload mime error'}");
} else {
var mime = result.toLowerCase().split('/');
if (mime[0] != 'image') {
res.status(400).send("{error:'Upload not an image', mime: '" + result + "'}");
} else {
// Read the image file
fs.readFile(image.path, function (err, data) {
if (err) {
res.status(400).send("{error:'Upload read error'}");
} else {
var hash = crypto.createHash('md5').update(data).digest("hex");
req.app.models.image.count({'hash': hash}, function (err, count) {
if (err) {
res.status(400).send("{error:'ORM Error: '" + JSON.stringify(err) + "'}");
} else {
if (count > 0) {
res.status(400).send("{error:'Image already exists'}");
} else {
var hash = crypto.createHash('md5').update(data).digest("hex");
var newPath = path.join(req.app.tempDir, hash);
fs.writeFile(newPath, data, function (err) {
if (err) {
res.status(400).send("{error:'Upload write error'}");
} else {
// Save the image
req.app.models.image.create([{
'hash' : hash,
'mime' : mime,
title : '',
description : ''
}], function(err, images) {
if (err) {
fs.unlink(newPath);
res.status(400).send("{error:'" + err.message + "'}");
} else {
res.status(200).send("{id:'" + images[0].id + "}");
}
});
}
});
}
}
});
}
});
}
}
});
}
答案 0 :(得分:5)
http://callbackhell.com/提供了适应异步编程的指南。
评论中的一些后续行动:
答案 1 :(得分:2)
<shamelessPlug>
我经历了回调意大利面的过程 - &gt;承诺意大利面 - &gt;写了我自己的承诺管理库
That library is available here
... and this describes the above process in a bit more detail
</shamelessPlug>
在任何情况下,一般的答案都是肯定的 - 你最终会收到一堆回调。为了阻止这种情况发生,最好通过回调管理系统或承诺服务。
哪种方法最好?这真的取决于你,你喜欢什么。
答案 2 :(得分:1)
我发现承诺的概念对此有很大帮助。 JavaScript中有许多promises实现,但想法是一样的。你可以从这个开始:
答案 3 :(得分:1)
来一个人。你真的认为你需要一个库吗?你可以用纯JavaScript来处理它。这是重写的代码:
var response = null,
request = null;
var fileDetected = function(err, result) {
if (err) {
response.status(400).send("{error:'Upload mime error'}");
} else {
var mime = result.toLowerCase().split('/');
if (mime[0] != 'image') {
response.status(400).send("{error:'Upload not an image', mime: '" + result + "'}");
} else {
// Read the image file
fs.readFile(image.path, onReadFile);
}
}
}
var onReadFile = function(err, data) {
if (err) {
response.status(400).send("{error:'Upload read error'}");
} else {
var hash = crypto.createHash('md5').update(data).digest("hex");
request.app.models.image.count({'hash': hash}, onImageCount);
}
}
var onImageCount = function(err, count) {
if (err) {
response.status(400).send("{error:'ORM Error: '" + JSON.stringify(err) + "'}");
} else {
if (count > 0) {
response.status(400).send("{error:'Image already exists'}");
} else {
var hash = crypto.createHash('md5').update(data).digest("hex");
var newPath = path.join(request.app.tempDir, hash);
fs.writeFile(newPath, data, onFileWrite);
}
}
}
var onFileWrite = function(err) {
if (err) {
response.status(400).send("{error:'Upload write error'}");
} else {
// Save the image
request.app.models.image.create([{
'hash' : hash,
'mime' : mime,
title : '',
description : ''
}], function(err, images) {
if (err) {
fs.unlink(newPath);
response.status(400).send("{error:'" + err.message + "'}");
} else {
response.status(200).send("{id:'" + images[0].id + "}");
}
});
}
}
exports.post = function (req, res) {
request = req;
response = res;
var image = request.files.image;
if (typeof(image) == 'undefined') {
response.status(400).send("{error:'Upload error'}");
return;
}
var magic = new Magic(mmm.MAGIC_MIME_TYPE);
magic.detectFile(image.path, fileDetected);
}
好的部分是,通过将不同功能中的所有内容分开,您实际上将逻辑拆分为块。新创建的函数的名称说明了块的用途。
答案 4 :(得分:0)
如果您需要评论某些内容是“加载图片”或“保存图片”,将其提取到单独的函数中将有助于提高可读性,降低缩进级别,并消除对评论的需求。
即。而不是写作
// ...
petAHorse(function(horsesResponse) {
// ...
})
// ...
你可以写
function horsePettedHandler(horsesResponse) {
// ...
}
// ...
petAHorse(horsePettedHandler);
// ...
答案 5 :(得分:0)
我更愿意使用node-sync lib而不是承诺。因为它允许一个伟大的事情:你不必为promises包装async libs函数,你可以使用特殊的语法。像这样:
var result = thirdPartyLibAsyncFunction.sync(null, 2, 3);
它以相同的方式使用您自己的代码。