javascript - 使用错误记录处理处理管道的惯用功能方法是什么?

标签 javascript functional-programming idioms

任何人都可以建议使用惯用的功能方法来处理带有错误日志记录的管道。命令式样式示例(在 JavaScript 中):

const filesToProcess = ['file1.txt','file2.txt','non_existent_file.txt'];

var totalLetterCountImperative = 0;
for (var i = 0; i < filesToProcess.length; i++){
    try {
        totalLetterCountImperative += fs.readFileSync(filesToProcess[i],'utf8').length;
    } catch (e) {
        console.log("There is an error whilst processing file: " + filesToProcess[i] + ". Hence, it's skipped. Error: " + e.message);
    }
}
console.log("Total Letter Count: " + totalLetterCountImperative);

下面的尝试可行,但看起来笨拙且笨拙。此外,它并非对所有错误都是通用的:

const filesToProcess = ['file1.txt','file2.txt','non_existent_file.txt'];

const totalLetterCount = filesToProcess
                          .filter(f => fs.existsSync(f))
                          .map(f => fs.readFileSync(f,'utf8').length)
                          .reduce((a,b) => a+b);

filesToProcess
  .filter(f => !fs.existsSync(f))
  .map(f => console.error("There is an error whilst processing file: " + f +". Hence it's skipped. Error: File doesn't exist"));

console.log("Total Letter Count: " + totalLetterCount);

我阅读了有关 Either 的用法。如果这确实是惯用的方式,那么有人可以举个例子并建议使用一个好的 JavaScript 库吗?

谢谢。

最佳答案

在处理的每个步骤中,您都会生成“字母计数”或“控制台消息”结果。解决此问题的最简单最直接的方法之一是让您的第一遍创建这些值的异构列表,然后进行第二遍将它们分成两个同类列表:

const filesToProcess = ['file1.txt','file2.txt','non_existent_file.txt'];

var results = filesToProcess.map(function(f){
    try {
        var n = readFileSync(filesToProcess[i],'utf8').length;
        return {tag:"count", value: n};
    } catch (e) {
        var msg = "There is an error whilst processing file: " + filesToProcess[i] + ". Hence, it's skipped. Error: " + e.message);
        return {tag:"err", value:msg};
    }
})

var totalLetterCount =
    results
      .filter(r => r.tag === "count")
      .map(r => r.value)
      .reduce((a,b)=> a + b);

results
  .filter(r => t.tag == "error")
  .map(r => r.value)
  .map(msg => console.error(msg));

但是,在我看来,更好的解决方案可能是利用副作用并使用 console.error,就像您已经在命令式代码段中所做的那样。通过这种方式,您无需将求和和记录错误的横切关注点混合在一起,最终得到的结果与坚持“纯函数式”解决方案时得到的结果非常相似。

当我在 Ocaml 中编程时,我一直在做这种事情。使用副作用将“记录的”值附加到某处的队列比重构所有内容以使用复杂的 monad 和/或 monad 更改器(mutator)要简单得多。

关于javascript - 使用错误记录处理处理管道的惯用功能方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40838008/

相关文章:

javascript - 使用 Angular $resource 自动保存

javascript - 错误: ENOENT: no such file or directory even when file exists in Firebase Cloud Functions

javascript - XUL MenuItem 在动态添加弹出窗口后消失

lambda - 为什么`id id`在OCaml中不是值?

f# - 具有功能数据结构的死 clown

ruby - 用于分解方法定义的惯用 Ruby

javascript - 为什么DIV不遵循父级的属性

Swift 变异函数作为一等值

list - 在 Groovy 中以惯用方式获取列表的第一个元素

clojure - 这个简单逻辑的惯用 Clojure 是什么?