2014-12-26 33 views
1

我开始使用OS.File模块中的OS.File.DirectoryIterator执行一些脚本。我已经得到了以下代码块的工作...有点。从JavaScript中返回数组OS.File.DirectoryIterator

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

不可否认,我对承诺没有经验,所以我确信问题在于我如何构建它(它从OS.File.DirectoryIterator上的MDN页面解除)。所以我的问题是:为什么数组可以在promise中访问,但不在外?

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. 
+0

见https://developer.mozilla.org/en-US/docs/JavaScript_OS.File/OS.File_for_the_main_thread – guest271314

回答

1

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

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

因此,在一条线上你不能访问subDirNames同步像你这样,因为I/O还没有完成,而是可以在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 
}); 
+0

@benjamin - 感谢您的详细解释和例子。这为我解决了一些事情。我能够用你的例子来做我所需要的。然而,这带来了更多的问题...... 在你的链式例子中,p2.then是否每次调用时都实际执行promise?换句话说,如果我调用p2.then,那么每次我需要对数组subDirNames执行一些操作时,是否正在执行的目录的另一个迭代? – user3402292

+0

@ user3402292可以随意在StackOverflow中提出尽可能多的问题。每个线程最好保留一个问题,以便您可能想要打开一个新问题。如果你觉得这个答案考虑[接受答案](http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work) –