gpt4 book ai didi

node.js - 重构嵌套回调、node.js、异步

转载 作者:搜寻专家 更新时间:2023-10-31 22:30:20 25 4
gpt4 key购买 nike

function indexArticles(callback) {
fs.readdir("posts/", function(err, files) {
async.map(files, readPost, function(err, markdown) {
async.map(markdown, parse, function(err, results) {
async.sortBy(results, function(obj, callback) {
callback(err, obj.date);
}, function(err, sorted) {
callback( {"articles": sorted.reverse()} );
});
});
});
});
}

我正在尝试弄清楚如何让它更漂亮——正如您所知道的,我正在使用 caolan 的异步库,但我不确定要使用哪个控制流结构。例如,如果我使用 async.waterfall,似乎会产生更多的代码,每个步骤都必须包含在一个匿名函数中。例如,这只是带有 waterfall 的嵌套版本的前两行:

function indexArticles(callback) {
async.waterfall([
function(callback) {
fs.readdir("posts/", function(err, files) {
callback(err, files)
})
},

function(files, callback) {
async.map(files, readPost, function(err, markdown) {
callback(err, markdown)
})
}])
}

你会如何改进它?

如果有一种方法不仅可以从左侧部分应用参数,那么我可以看到这样做,例如,

function indexArticles(callback) {
async.waterfall([
async.apply(fs.readdir, "posts/"),
async.apply(async.map, __, readPost),
async.apply(async.map, __, parse),
// etc...
])
}

最佳答案

这是一个有趣的问题,因为您需要将参数绑定(bind)到迭代器函数的左侧和右侧,所以 bind/和 bindRight(的StackOverflow 上有一些实现)对你有用。这里有几个选项供您选择:

(1) 首先,在您的 async.waterfall 示例中,您有:

function(callback) {
fs.readdir("posts/", function(err, files) {
callback(err, files)
})
}

这与:

function(callback) {
fs.readdir("posts/", callback)
}

使用 Function.bind 和这个方法,你的整个函数 indexArticles 可以写成:

function indexArticles(callback) {
async.waterfall([
fs.readdir.bind(this, 'posts/'),
function(files, cb) { async.map(files, readPost, cb); },
function(text, cb) { async.map(text, parse, cb); },
function(results, cb) { async.sortBy(results, function(obj, callback) {
callback(null, obj.date);
}, cb) }
], function(err, sorted) {
callback( {"articles": sorted.reverse()} );
});
};

哪个更短。

(2) 如果您真的想避免包装函数,您可以使用一种偏函数应用程序。首先,在文件的顶部(或模块等),定义一个名为 partial 的函数:

var partial = function(fn) {
var args = Array.prototype.slice.call(arguments, 1);
return function() {
var currentArg = 0;
for(var i = 0; i < args.length && currentArg < arguments.length; i++) {
if (args[i] === undefined)
args[i] = arguments[currentArg++];
}
return fn.apply(this, args);
};
}

此函数接受一个函数和任意数量的参数,并在调用该函数时用实际参数替换参数列表中的 undefined 值。然后你会像这样使用它:

function indexArticles(callback) {
async.waterfall([
fs.readdir.bind(this, 'posts/'),
partial(async.map, undefined, readPost, undefined),
partial(async.map, undefined, parse, undefined),
partial(async.sortBy, undefined, function(obj, callback) {
callback(null, obj.date);
}, undefined)
], function(err, sorted) {
callback( {"articles": sorted.reverse()} );
});
}

因此,partial(async.map, undefined, readPost, undefined) 返回一个函数,当异步库调用 fn(files, callback) 时,它为第一个 undefined 填充 files,为第二个 undefined 填充 callback,最后调用 async.map(files, readPost, callback).

(3) Function.prototype 还有一个partial 的版本在this StackOverflow answer ,允许您使用语法:async.map.partial(undefined, readPost, undefined);但是,我可能会建议不要以这种方式修改 Function.prototype,而是将 partial 用作函数。

最后,哪种方法最具可读性和可维护性取决于您。

关于node.js - 重构嵌套回调、node.js、异步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11514534/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com