在Javascript中从嵌套函数中访问变量

时间:2013-02-12 10:52:00

标签: javascript function nested

我有以下功能:

downloadProductImage: function(remoteImage, localImageName){
    window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fileSystem) {
        fileSystem.root.getFile(localImageName, {create: true, exclusive: false}, function(fileEntry) {
            var localPath = fileEntry.fullPath;
            var ft = new FileTransfer();
            ft.download(remoteImage,
                localPath, function(entry) {
                    //RETURN THIS imageURL = entry.fullPath;

                }, fail);
        }, fail);
    }, fail);       
}   

函数downloadProductImage()位于全局var app = {}中,因此可以通过app.downloadProductImage()访问。

这个函数在一个循环中运行,我希望返回imageURL,但似乎无法得到它。我在var app = {}之外声明了全局var = imageURL但是每当我尝试在另一个函数中获取imageURL时,第一个循环返回undefined,其余的都是正确的。

我不确定为什么第一个循环返回undefined .. var imageURL在页面顶部全局声明..

如果我在上面的代码中警告(imageURL)// RETURN THIS imageURL = entry.fullPath;,它会正确发出警报,而不是当我尝试在函数外部访问它时

1 个答案:

答案 0 :(得分:0)

鉴于@dfsq提到这是一个异步调用,我相信当你在顶层访问它时会发现imageURL是未定义的,因为还没有调用回调。

确认这一点的最简单方法是在回调中插入两个console.log()语句,就在设置imageURL之前,之后;和另外两个console.log()语句围绕顶层代码中访问imageURL的点。

如果在分配之前确实发生了访问,那么这将解释为什么你会看到“未定义”。要解决您的问题,您需要推迟在顶层处执行的任何操作,直到回调完成为止。 jQuery promise是实现此目的的一种方法,但其他库中也有其他选项。在您正在使用的任何库中查找“期货”,“承诺”,“延期执行”作为关键字。如果您正在使用任何类型的事件框架,您也可以使用它:在回调中触发事件,并在顶层侦听事件(确保在触发之前监听,否则您将遇到相反的问题)。< / p>

如果您使用的是jQuery,那么以下内容可能会为您提供一个先机:

var imageURLPromise = jQuery.Deferred();

downloadProductImage: function(remoteImage, localImageName){
    window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fileSystem) {
        fileSystem.root.getFile(localImageName, {create: true, exclusive: false}, function(fileEntry) {
            var localPath = fileEntry.fullPath;
            var ft = new FileTransfer();
            ft.download(remoteImage,
                localPath, function(entry) {
                    // Note: The assignment is mediated by the DeferredObject that handles the timing issues for us.
                    imageURLPromise.resolve(entry.fullPath);
                }, fail);
        }, fail);
    }, fail);       
}   

imageURLPromise.done(function(imageURL) {
    // Use imageURL here at toplevel.
});