【问题标题】:Wrapping fs.readFile in a generator/yield在生成器/产量中包装 fs.readFile
【发布时间】:2014-03-20 11:33:55
【问题描述】:

我正在尝试了解 JavaScript 和 Node.js 中的生成器和产量,但遇到了一个问题。

理想情况下,我想做的是用生成器/yield 包装 fs.readFile,这样我就可以同步使用它而不会阻塞任何东西。

我想出了以下代码:

function readFileSync (path) {
    return (function *(){
        return yield require('fs').readFile(path, function *(err, data){
            yield data;
        });
    })();
}

console.log(readFileSync('test-file.txt'));

但不幸的是,readFileSync 总是返回 {} 而不是文件内容。

希望我想要实现的目标仍然是可能的,或者我完全错过了生成器/产量的意义,并且我完全错误地使用它,在这种情况下指出我哪里出错了,任何资源都会很棒。

【问题讨论】:

  • 在我见过的所有生成器示例中,都涉及到 Promise。您的脚本基于哪些文档/帖子/howtos?
  • 为什么不直接使用fs.readFileSync
  • Why not simply use fs.readFileSync? 阻塞了。这里的用例是让这条线非阻塞:github.com/bevry/ssg-experiments/blob/…
  • In all generator examples I've seen were promises involved. On which docs/posts/howtos is your script based? 没有具体的例子,因为没有什么是我所追求的,所以这只是我最好的猜测的混搭......
  • “同步”表示“阻塞”。我认为这是不可能的,请查看How to encapsulate async function calls into a sync function in Node.js or Javascript

标签: javascript node.js generator yield


【解决方案1】:

稍微去糖化和更新(似乎raise 被重命名为throwlgersman's 回答使其与io.js 1.0.4 一起工作:

function run(gen) {
  var iter = gen(function (err, data) {
    if (err) { iter.throw(err); }
    return iter.next(data);
  });
  iter.next();
}

run(function* (resume) {
  var contents = yield require('fs').readFile(path, resume);
  console.log(contents);
});

谢谢你!

【讨论】:

    【解决方案2】:

    如何使用启用了和谐功能的节点(node --harmony)和这个超级简单的 ES6 sn-p:

    function run( gen, iter) {
      (iter=gen( (err, data) => (err && iter.raise(err)) || iter.next(data))).next();
    }
    
    run(function* (resume) {
        var contents = yield require('fs').readFile(path, resume);
        console.log(contents);
    });
    

    您可以在orangevolt.blogspot.com 这篇文章中阅读更多关于这个死的简单模式的信息(并在线试用)

    【讨论】:

      【解决方案3】:

      你可以使用像 Wait.for-ES6 这样的辅助库(我是作者)

      专业版:您可以按顺序调用任何标准的异步 node.js 函数

      骗局:你只能在生成器中做到这一点function*

      使用fs.readdirfs.readfile 的示例(两者都是标准异步node.js 函数

      var wait=require('wait.for-es6'), fs=require('fs');
      
      function* sequentialTask(){
         var list = yield wait.for(fs.readdir,'/home/lucio');
         console.log(list); // An array of files
         var data = yield wait.for(fs.readFile,list[0]); //read first file
         console.log(data); // contents
      }
      
      wait.launchFiber(sequentialTask);
      

      【讨论】:

        【解决方案4】:

        用生成器将异步函数变成同步函数是不可能的。

        生成器可以中断自己,但不能中断其他函数的控制流。

        所以你的代码如何工作的唯一方法是它是否在另一个生成器中:

        console.log(yield* readFileSync('test-file.txt'));
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-12-22
          • 2011-09-18
          • 2016-06-16
          • 1970-01-01
          • 2020-01-18
          • 2021-10-28
          • 1970-01-01
          相关资源
          最近更新 更多