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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 20:10:51  来源:igfitidea点击:

Passing a variable to an asynchronous function (promise) in javascript

javascriptasynchronous

提问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);
}

MDN Closure

MDN 关闭

回答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.

阅读承诺,它们值得被理解。