从JavaScript OS.File.DirectoryIterator返回一个数组

时间:2014-12-26 23:23:18

标签: javascript arrays promise

我开始使用OS.File模块中的OS.File.DirectoryIterator来编写脚本。我已经得到了以下代码块......有点像。

我尝试做的是遍历给定目录(有4个子目录)并将子目录的名称放入数组中。挂起的是,数组按预期填充,但在promise构造之外不可用。

不可否认,我对承诺缺乏经验,所以我确定问题在于我是如何构建的(这是从OS.File.DirectoryIterator上的MDN页面解除的)。所以我的问题是:为什么数组可以在承诺范围内访问,但不在它之外?

var iterator = new OS.File.DirectoryIterator(PathToDir);
var subDirNames = [];

var promise = iterator.forEach(
   function(entry) {
      subDirNames.push(entry.name);
   }
);

promise.then(
   function(success) {
      iterator.close();
      console.log("--> "+subDirNames[1]); \\Array element 1 display in console fine.
      return subDirNames;
   },
   function(failure) {
      console.log("--> Error: "+failure);
   }
);
console.log("--> "+subDirNames[1]); \\Array element 1 displays as undefined.

1 个答案:

答案 0 :(得分:1)

在特殊情况下,JavaScript中的并发模型如下:

  • 代码始终同步从第一行到最后一行。事情一个接一个地发生。
  • 触及I / O的所有内容(如文件系统或Web访问)都会立即返回,而是通过回调或返回承诺来报告完成情况。
  • 解开承诺是在不同的范围内完成的。

因此,在行中,您无法像执行I / O那样同步访问subDirNames,而是可以检测I / O的时间完成了一个承诺。幸运的是,这是一个发电机附件,所以你也有替代选择。

直接承诺接近

信守承诺:

var p2 = promise.then(... /* your iterator.close() code here */); // new promise
//... run more code
// when you need to access subDirNames
p2.then(Function(names){
    console.log(names[1]); // will always work. 
});

这是并发模型 - 它非常有用,它避免了很多线程问题。

发电机

由于您直接为Firefox开发了一些内容,因此没有浏览器兼容性问题,可以使用EcmaScript 6的可用功能。我们可以使用生成器来暂停执行某个功能并等待结果 - 首先是小帮手:

function async(gen){ "use strict"; // this takes a generator
    gen = gen(); // starts it
    return Promise.resolve().then(function cont(a){
        var n = gen.next(a); // gets the next element
        if(n.done) return Promise.resolve(n.value); // a `return` 
        if(!n.value.then) return cont(n.value); // yield plain value
        return n.value.catch(gen.throw.bind(gen)).then(cont);
    });
}

您可以从这样的图书馆获取此功能,而不是您喜欢(他们做得更快,但这并不重要)。

这可以让你做类似的事情:

async(function*(){
    var iterator = new OS.File.DirectoryIterator(PathToDir);
    // optimally you'd do yield* iterator but this API predates modern iterators
    var subDirNames = [];
    yield iterator.forEach(function(entry) { // note the yield
        subDirNames.push(entry.name);
    });
    iterator.close();
    console.log(subDirNames[1]); // will log correctly
});