缓存JavaScript承诺结果

dip*_*ipu 3 javascript promise

我会打一个电话到服务器以获得项目列表。如何确保只进行一次调用,并且仅处理一次集合以创建键值映射。

var itemMap = {};

function getItems(){
    getAllItemsFromServer().then(function(data){
     data.forEach(value){
       itemMap[value.key] = value;
     }});
     return itemMap;

}

//need to get the values from various places, using a loop here  
//to make multiple calls
var itemKeys = ['a', 'b', 'c'];
itemKeys.forEach(key){
   var value = getItems().then(function(data){ return data[key]});
   console.log('item for key=' + value);
}
Run Code Online (Sandbox Code Playgroud)

Ori*_*ori 6

一个承诺是有状态的,一旦它被实现,它的值就不能改变。您可以.then多次使用来获取其内容,并且每次都会得到相同的结果。

getAllItemsFromServer 函数返回一个承诺,then块操作响应并返回itemMap,它被包装在一个响应中(承诺链)。承诺然后被缓存,可用于itemMap 重复获取。

var itemsPromise = getItems(); // make the request once and get a promise

function getItems(){
    return getAllItemsFromServer().then(function(data){
       return data.reduce(function(itemMap, value){
          itemMap[value.key] = value;
          return itemMap;
       }, {});
    });
}

//need to get the values from various places, using a loop here  
//to make multiple calls
var itemKeys = ['a', 'b', 'c'];
itemKeys.forEach(function(key){
    itemsPromise.then(function(data){ 
        return data[key];
    }).then(function(value) {
       console.log('item for key=' + value);
    });
});
Run Code Online (Sandbox Code Playgroud)


Ber*_*rgi 6

我认为你真正想要的是

var cache = null; // cache for the promise
function getItems() {
    return cache || (cache = getAllItemsFromServer().then(function(data){
        var itemMap = {};
        data.forEach(function(value){
            itemMap[value.key] = value;
        });
        return itemMap;
    }));
}

var itemKeys = ['a', 'b', 'c'];
itemKeys.forEach(function(key){
    getItems().then(function(data){
        return data[key];
    }).then(function(value) {
        console.log('item for key=' + value);
    }); // notice that you get the value only asynchronously!
});
Run Code Online (Sandbox Code Playgroud)


Ben*_*aum 5

我将添加一个用于缓存promise操作的通用方法。这里的窍门是,通过将promise作为值的真实代理并缓存它而不是值,我们避免了竞争条件。这同样适用于非承诺函数,说明了承诺如何很好地捕捉异步+值的概念。我认为这可以帮助您更好地理解问题:

function cache(fn){
    var NO_RESULT = {}; // unique, would use Symbol if ES2015-able
    var res = NO_RESULT;
    return function () { // if ES2015, name the function the same as fn
        if(res === NO_RESULT) return (res = fn.apply(this, arguments));
        return res;
    };
}
Run Code Online (Sandbox Code Playgroud)

这将使您可以非常轻松地缓存任何承诺(或非承诺操作):

 var getItems = cache(getAllItemsFromServer);


 getItems();
 getItems();
 getItems(); // only one call was made, can `then` to get data.
Run Code Online (Sandbox Code Playgroud)

请注意,您不能使其“同步”