1

我正在尝试编写一个localStorage类似于 Rails 获取缓存结果的小包装器。在 Rails 中,模式是这样的:

# Data.find is a block which just returns the data if the cache key was not found
data = Rails.cache.fetch(key, options) { Data.find }

在 JavaScript 中,我很难获得回调的结果,如果缓存为空,则执行该回调以返回数据。

function fetch(key, callback) {
    var result = localStorage.getItem(key);
    if (result) {
        return JSON.parse(result);
    } else {
        result = callback();
        if (result) {
            result = JSON.stringify(result);
            localStorage.setItem(key, result);
        }
        return result;
    }
}

我正在尝试像这样使用它:

var data = fetch('projects-delivered', function() {
    var result;
    d3.json('/projects/delivered.json', function(data) {
        result = formatDates(data);
    });
    return result;
});

但是,数据始终是未定义的。我是否需要传入另一个回调,或者同步一些如何?或者,这难道不是 JavaScript 的异步特性吗?

4

1 回答 1

4

您的 AJAX 异步运行,因此您的回调将始终返回undefined.

您必须从getData函数中调用回调:

function fetch(key, getData, callback) {
    var result = localStorage.getItem(key);

    result ? callback(JSON.parse(result)) : getData(function (result) {
        result && localStorage.setItem(key, JSON.stringify(result));

        callback(result);
    }
}

像这样使用它:

fetch('projects-delivered', function (callback) {
    d3.json('/projects/delivered.json', function (data) {
        callback(formatDates(data));
    });
}, function (data) {
    // Use the data
});

或者,您可以从您的fetch函数返回一个承诺:

function fetch(key, getData) {
    var result = localStorage.getItem(key);

    if (result) return Promise.resolve(JSON.parse(result));

    return new Promise(function (resolve) {
        getData(function (result) {
            result && localStorage.setItem(key, JSON.stringify(result));

            resolve(result);
        });
    });
}

然后使用返回的承诺:

var promise = fetch('projects-delivered', function (callback) {
    d3.json('/projects/delivered.json', function (data) {
        callback(formatDates(data));
    });
});

promise.then(function (data) {
    // Use the data
});
于 2012-10-16T21:42:04.377 回答