函数编程中的nodejs createReadStream

时间:2018-10-22 19:37:51

标签: javascript node.js typescript functional-programming fp-ts

对于使用fp-ts或出于学习目的的其他函数式编程库对TaskEither的用法,我希望获得您的反馈:

  • 我在处理Node.js流时使用Promise,以这种方式使用Promise是一个好的解决方案吗?最直接的替代方法是什么?
  • 我正在使用.run().then(...).fold,您知道使用我的函数的更简洁的方法吗?
  • 是否可以在没有Either的情况下使用Promise重写相同的代码?您能提供样品吗?

export const md5 = (path: string): TaskEither<string, string> => {
  const mkHash = (p: string) =>
    new Promise<string>((resolve, reject) => {
      const hash = createHash("md5");
      const rs = createReadStream(p);
      rs.on("error", (error: Error) => reject(error));
      rs.on("data", chunk => hash.update(chunk));
      rs.on("end", () => {
        return resolve(hash.digest("hex"));
      });
    });
  return tryCatch<string, string>(
    () => mkHash(path).then(x => x),
    message => `cannot create md5 hash: ${message}`
  );
};

it("should return right and create md5 hash for a file", () => {
    md5(fileName)
      .run()
      .then(e =>
        e.fold(console.log, r => {
          expect(r).toBe("SD8ddDad0756a93ded72b823b19dd877");
        })
      );
  });

  it("should return left with an error message", () => {
    md5(BAD_PATH)
      .run()
      .then(e =>
        e.fold(error => expect(error).toContain("ENOENT"), () => ({}))
      );
  });

2 个答案:

答案 0 :(得分:1)

我将使用2来完成此任务。这是Promise库的一元经延迟评估的替代方法,可以包装或生成Promise,但它可以单独使用:

export const md5 = path =>
    Future ((reject, resolve) => {
      const hash = createHash ("md5")
      const rs = createReadStream (p)

      rs.on("error", reject);
      rs.on("data", chunk => hash.update (chunk));
      rs.on("end", () => {
        resolve (hash.digest ("hex"));
      })
    })
}

const eventualMd5 = md5('[path]')

Future.fork (console.error) (console.log) (eventualMd5)

基本上,您可以充分利用Either在异步流上的优势,并使用许多相关工具来分叉代码并处理错误和成功情况。

答案 1 :(得分:0)

部分答案:我只能使用Either而不使用Promise来重写此功能。我对替代解决方案仍然非常感兴趣。

export const md5 = (path: string): Either<string, string> => {
  const BUFFER_SIZE = 8192;
  let fd;
  try {
    fd = openSync(path, "r");
    const buffer = Buffer.alloc(BUFFER_SIZE);
    const hash = createHash("md5");
    let bytesRead;
    do {
      bytesRead = readSync(fd, buffer, 0, BUFFER_SIZE, 0);
      hash.update(buffer.slice(0, bytesRead));
    } while (bytesRead === BUFFER_SIZE);
    return right(hash.digest("hex"));
  } catch (error) {
    return left(error.message);
  } finally {
    if (fd !== undefined) {
         closeSync(fd);
    }
  }
};

  it("should return right and create md5 hash for a file", () => {
    const mk = md5(fileName);
    assert.strictEqual(mk.isLeft(), false);
    assert.strictEqual(mk.isRight(), true);
    assert.strictEqual(mk.value, "SS8dd3ad07e6a93ded72b823b19dd877");
  });

  it("should return left return an error message", () => {
    const mk = md5(BAD_PATH);
    assert.strictEqual(mk.isLeft(), true);
    assert.strictEqual(mk.isRight(), false);
    assert.strictEqual(mk.value.includes("ENOENT"), true);
  });