在javascript中将变量传递给异步函数(promise)

时间:2014-01-15 14:03:36

标签: javascript asynchronous

我有以下代码循环运行

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();
    });
}

我遇到的问题是我试图将具有2个属性的对象保存到数组中。该对象应具有标识符和结果。 (分别是fileName和fileURL)。但由于此函数是异步的(通过promise执行)。到“getFileAsBlob”结束时,currentImageName已经更新,最终以我的许多具有相同标识符的对象结束(最后一个在完成之前处理)。

这可能是一个非常简单的问题,但我对javascript很新,还没有找到任何相关内容。

我认为解决方案可能是将变量传递给“done”函数,但我认为这个函数是方法返回的函数,并且已经设置了。 (我不知道它的样子)

编辑:

代码就在普通循环中

for (x = 0; x<fileNames.length; x++)

2 个答案:

答案 0 :(得分:9)

因此创建一个函数,以便无法更改变量

function getFile (filmName, imageName) {
    reader.getFileAsBlob(fileName)
    .done(function(blob) {
        picturesFilePathArray.push({
           fileName: imageName,
           fileURL: blobURL(blob)
        });
       refreshKMZList();
    });
}

并将其命名为

if (currentImageName.indexOf(".jpg") != -1) {
    getFile (fileNames[x], currentImageName);
}

或者您可以执行类似

的操作
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

答案 1 :(得分:4)

此问题的解决方案始终相同:使用闭包。

但是,由于您使用的是基于承诺的库,因此您有更好的选择。使用承诺。 (当然,这也是基于闭包的。它只是一个很多更好的抽象。)

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

现在你可以这样做,每个文件调用一次refreshKMZList()

fileNames.filter(isJpg).forEach(function (path) {
    getFileInfo(path).then(function (fileInfo) {
        picturesFilePathArray.push(fileInfo);
        refreshKMZList();
    })
    .catch(function (error) {
        // handle the error
    });
});

甚至是这样,其中refreshKMZList()每次只调用一次:

var fileInfos = fileNames.filter(isJpg).map(getFileInfo);

Promise.all(fileInfos).then(function (arrayOfFileInfo) {
    picturesFilePathArray.concat(arrayOfFileInfo);
    refreshKMZList();
})
.catch(function (error) {
    // handle the error
});

阅读承诺,值得理解。