javascript 在javascript中将变量传递给异步函数(promise)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21139504/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Passing a variable to an asynchronous function (promise) in javascript
提问by Pochi
I have the following code which runs in a loop:
我有以下循环运行的代码:
var index = fileNames[x].lastIndexOf("/") + 1;
var currentImageName = fileNames[x].substr(index);
if (currentImageName.indexOf(".jpg") != -1) {
reader.getFileAsBlob(fileNames[x])
.done(function(blob) {
picturesFilePathArray.push({
fileName: currentImageName,
fileURL: blobURL(blob)
});
refreshKMZList();
});
}
The problem I am having is that I am trying to save an object with 2 properties into an array. This object should have the identifier and the result. (fileName and fileURL respectively). But since this function is asynchronous (executed through a promise). By the time the "getFileAsBlob" finishes, currentImageName has already been updated ultimately ending in many of my objects having the same identifier (the last one processed before it finished).
我遇到的问题是我试图将一个具有 2 个属性的对象保存到一个数组中。这个对象应该有标识符和结果。(分别为fileName 和fileURL)。但是由于这个函数是异步的(通过承诺执行)。到“getFileAsBlob”完成时,currentImageName 已经更新,最终以我的许多具有相同标识符的对象结束(最后一个在完成之前处理)。
This might be a really easy problem, but I am very new to javascript and haven't yet found anything about it.
这可能是一个非常简单的问题,但我对 javascript 很陌生,还没有找到任何关于它的东西。
I thought that the solution might be in passing the variable to the "done" function, but I think this function is the one being returned by the method and is already set. (I dont know how it looks)
我认为解决方案可能是将变量传递给“完成”函数,但我认为这个函数是方法返回的函数并且已经设置。(不知道长什么样)
Edit:
编辑:
The code is just inside a normal loop
代码只是在一个普通的循环中
for (x = 0; x<fileNames.length; x++)
回答by epascarello
So create a function so the variable can not be changed
所以创建一个函数,这样变量就不能改变了
function getFile (filmName, imageName) {
reader.getFileAsBlob(fileName)
.done(function(blob) {
picturesFilePathArray.push({
fileName: imageName,
fileURL: blobURL(blob)
});
refreshKMZList();
});
}
and call it
并称之为
if (currentImageName.indexOf(".jpg") != -1) {
getFile (fileNames[x], currentImageName);
}
or you can do something like
或者你可以做类似的事情
if (currentImageName.indexOf(".jpg") != -1) {
(function (fileName, imageName) {
reader.getFileAsBlob(fileName)
.done(function(blob) {
picturesFilePathArray.push({
fileName: imageName,
fileURL: blobURL(blob)
});
refreshKMZList();
});
})(fileNames[x], currentImageName);
}
回答by Tomalak
The solution to this problem is always the same: Use a closure.
这个问题的解决方案总是一样的:使用闭包。
But since you are using a promise based library, you have a nicer option. Use promises. (Internally this is based on closures as well, of course. It's just a muchnicer abstraction.)
但是由于您使用的是基于 Promise 的库,因此您有更好的选择。使用承诺。(内部这是基于关闭为好,当然,这只是一个多更好的抽象。)
function getFileInfo(path) {
return reader.getFileAsBlob(path).done(function (blob) {
return {
fileName: path.split('/').pop(),
fileURL: blobURL(blob)
});
};
}
function isJpg(filename) {
return /\.jpg$/i.test(filename);
}
Now you can do this, where refreshKMZList()
is called once per file:
现在您可以执行此操作,refreshKMZList()
每个文件调用一次where :
fileNames.filter(isJpg).forEach(function (path) {
getFileInfo(path).then(function (fileInfo) {
picturesFilePathArray.push(fileInfo);
refreshKMZList();
})
.catch(function (error) {
// handle the error
});
});
or even this, where refreshKMZList()
is called only once per overall:
甚至这个,refreshKMZList()
每个整体只调用一次:
var fileInfos = fileNames.filter(isJpg).map(getFileInfo);
Promise.all(fileInfos).then(function (arrayOfFileInfo) {
picturesFilePathArray.concat(arrayOfFileInfo);
refreshKMZList();
})
.catch(function (error) {
// handle the error
});
Read up on promises, they are worth being understood.
阅读承诺,它们值得被理解。