文档 / 语言手册 / 惰性值
Edit

惰性值

如果你有一些昂贵的计算,你想延后计算并且缓存结果, 你可以使用 lazy 包装它:

ReScriptJS Output
// Read the directory, only once
let expensiveFilesRead = lazy({
  Js.log("Reading dir")
  Node.Fs.readdirSync("./pages")
})

检查 JS 输出标签页:尽管你已经声明了 expensiveFilesRead,但它的代码还没有执行!你可以随手拿着它,不用担心它进行目录读取。

注意:惰性值是不是一个共享数据类型。不要在你的 JavaScript 代码中依赖它的运行时表示。

执行惰性计算

要实际运行惰性值的计算,请使用全局模块 LazyLazy.force

ReScriptJS Output
// First call. The computation happens
Js.log(Lazy.force(expensiveFilesRead)) // logs "Reading dir" and the directory content

// Second call. Will just return the already calculated result
Js.log(Lazy.force(expensiveFilesRead)) // logs the directory content

第一次调用 Lazy.force 时,进行了昂贵的计算,而且结果被缓存了。第二次调用会直接使用缓存的值。

在第一次调用后你无法重新触发计算。确保你只在计算结果不改变的情况下使用惰性值(例如,一个昂贵的服务器请求,它的响应总是相同的)。

除了使用 Lazy.force,你也可以使用模式匹配来触发计算:

ReScriptJS Output
switch expensiveFilesRead {
| lazy(result) => Js.log(result)
}

因为模式匹配也可用于 let 绑定,你也可以这样做:

ReScriptJS Output
let lazy(result) = expensiveFilesRead
Js.log(result)

处理异常

为了完整起见,我们的文件读取例子可能因为 readdirSync 而引发一个异常。下面是处理方式:

ReScriptJS Output
let result = try {
  Lazy.force(expensiveFilesRead)
} catch {
| Not_found => [] // empty array of files
}

不过你应该在惰性计算内部处理这个异常。