How do I handle multiple browser scripts making the same calls to the back-end service(如何处理对后端服务进行相同调用的多个浏览器脚本)
问题描述
我有一个网页,其中的不同部分都需要相同的后端数据.每个都是孤立的,因此它们最终都会对后端进行相同的调用.
I have a web page where different parts of it all need the same back-end data. Each is isolated, so they each end up eventually making the same calls to the back-end.
当调用已经在进行中并由同一网页上的不同代码段启动时,避免调用 Web 服务器的最佳方法是什么?
What is the best way to avoid making a call to the web server when one is already in progress and initiated by a different piece of code on the same web page?
这是一个例子.我将使用 setTimeout 来模拟异步调用.
Here's an example. I'll use setTimeout to simulate an asynchronous call.
假设有一个异步函数返回联系人列表,在这个例子中它基本上是一个简单的字符串数组:
Let's assume there's an async function that returns the list of contacts, which is basically a simple array of strings in this example:
var getContacts = function() {
log('Calling back-end to get contact list.');
return new Promise(function(resolve, reject) {
setTimeout(function() {
log('New data received from back-end.');
resolve(["Mary","Frank","Klaus"]);
}, 3000);
});
};
现在,让我们创建三个单独的函数,每个函数都出于不同的目的调用上述函数.
Now, let's create three separate functions that each call the above function for different purposes.
转储联系人列表:
var dumpContacts = function() {
getContacts().then(function(contacts) {
for( var i = 0; i < contacts.length; i++ ) {
log( "Contact " + (i + 1) + ": " + contacts[i] );
}
});
};
确定特定联系人是否在列表中:
Determine if a particular contact is in the list:
var contactExists = function(contactName) {
return getContacts().then(function(contacts) {
return contacts.indexOf(contactName) >= 0 ? true : false;
});
};
获取第一个联系人的姓名:
Get the name of the first contact:
var getFirstContact = function() {
return getContacts().then(function(contacts) {
if ( contacts.length > 0 ) {
return contacts[0];
}
});
};
下面是一些使用这三个函数的示例代码:
And here is some example code to use these three functions:
// Show all contacts
dumpContacts();
// Does contact 'Jane' exist?
contactExists("Jane").then(function(exists){
log("Contact 'Jane' exist: " + exists);
});
getFirstContact().then(function(firstContact){
log("first contact: " + firstContact);
});
上述例程使用全局 log() 函数.可以使用 console.log() 代替.上面的 log() 函数记录到浏览器窗口,实现如下:
The above routines make use of a global log() function. console.log() could be used instead. The above log() function log's to the browser window and is implemented as follows:
function log() {
var args = Array.prototype.slice.call(arguments).join(", ");
console.log(args);
var output = document.getElementById('output');
output.innerHTML += args + "<br/>";
}
并且在 html 中需要以下内容:
and requires the following in the html:
<div id='output'><br/></div>
当上面的代码运行时,你会看到:
When the above code is run, you will see:
Calling back-end to get contact list.
和
New data received from back-end.
三遍,没必要.
如何解决这个问题?
此示例在 Plunker 上可以执行:http://plnkr.co/edit/6ysbNTf1lSf5b7L3sJxQ?p=preview
This sample is on Plunker can be executed: http://plnkr.co/edit/6ysbNTf1lSf5b7L3sJxQ?p=preview
推荐答案
只需在调用的函数中缓存结果即可:
Just cache the result in the function making the call:
function cache(promiseReturningFn){
var cachedVal = null; // start without cached value
function cached(){
if(cachedVal) return cachedVal; // prefer cached result
cachedVal = promiseReturningFn.apply(this, arguments); // delegate
return cachedVal; // after we saved it, return it
}
cached.flush = function(){ cachedVal = undefined; };
return cached;
}
这有一个警告,即对于 null 的实际结果会失败,否则它可以很好地完成工作.
This has the caveat of failing for actual results that are null but otherwise it gets the job done nicely.
您现在可以缓存任何 promise 返回函数 - 上面的版本只缓存忽略参数 - 但您可以构造一个类似的函数,它具有 Map 并基于不同的参数进行缓存 - 但让我们专注于您的用例.
You can now cache any promise returning function - the version above only caches ignoring arguments - but you can construct a similar one that has a Map and caches based on different arguments too - but let's focus on your use case.
var getContactsCached = cache(getContacts);
getContactsCached();
getContactsCached();
getContactsCached(); // only one async call ever made
cache 方法实际上甚至与 Promise 无关——它所做的只是获取一个函数并缓存它的结果——你可以将它用于任何事情.事实上,如果你正在使用像 underscore 这样的库,你可以使用 _.memoize
来为你做这件事.
The cache method is actually not even related to promises - all it does is take a function and cache its result - you can use it for anything. In fact if you're using a library like underscore you can use _.memoize
to do it for you already.
这篇关于如何处理对后端服务进行相同调用的多个浏览器脚本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:如何处理对后端服务进行相同调用的多个浏览器脚本
基础教程推荐
- 我可以在浏览器中与Babel一起使用ES模块,而不捆绑我的代码吗? 2022-01-01
- html表格如何通过更改悬停边框来突出显示列? 2022-01-01
- 用于 Twitter 小部件宽度的 HTML/CSS 2022-01-01
- 直接将值设置为滑块 2022-01-01
- Electron 将 Node.js 和 Chromium 上下文结合起来意味着 2022-01-01
- Vue 3 – <过渡>渲染不能动画的非元素根节点 2022-01-01
- 自定义 XMLHttpRequest.prototype.open 2022-01-01
- 如何使用TypeScrip将固定承诺数组中的项设置为可选 2022-01-01
- 如何使用JIT在顺风css中使用布局变体? 2022-01-01
- Chart.js 在线性图表上拖动点 2022-01-01