我开始使用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.
答案 0 :(得分:1)
在特殊情况下,JavaScript中的并发模型如下:
因此,在行中,您无法像执行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);
});
}
您可以从bluebird这样的图书馆获取此功能,而不是您喜欢(他们做得更快,但这并不重要)。
这可以让你做类似的事情:
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
});