场景:
行为:
当用户进入该站点时,他们会看到一系列书籍.其中一些已经在他们的"Read Later"列表中,有些则不是.
用户在每本书旁边都有一个指示,告诉他们该书是否已被添加到列表中.
我的问题
我在辩论哪种选择对我的情况是理想的.
选项1:
Pro: 对服务器的请求非常小,响应非常简单(真或假).
Con:在一本有30本书的页面中,我将发送30个单独的http请求,它们可以阻止套接字,并且考虑到浏览器和服务器必须为每个事务执行整个握手,这个请求相当慢.
选项2:
亲:我只提出一个请求,并立即更新所有书籍的指标.
Con: "Read Later"列表可能有数百本书,传递一个大数组可能会证明是缓慢而过度的.特别是在屏幕上没有出现30本书的情况下,只有2-3本.(也就是说,我想检查某个书是否在列表中,为此我让服务器从列表中向客户端发送整个书籍列表).
所以,
你会采用哪种方式来最大限度地提高性能:1还是2?
我有什么替代品吗?
Sta*_*kin 18
这个答案是用 JavaScript 编写的,并包含易于理解的代码示例。
OP 询问向“稍后阅读”API 发出请求的最有效方法是什么,每个请求都需要等待一段时间,而后端会保存书籍。
对于这个答案,我创建了一个“稍后阅读”API 端点的演示,每个请求都会随机等待 70-130 毫秒以保存每本书。
我每次都在所有场景中测试 30 本书。
最后,我们将通过专业地测量我们将采取的每个操作的真实运行时间来看到每种方法的最佳结果。
在这里,我们将通过 JS 同步运行每个调用。
代码:
async function saveBooksSync() {
console.time('save-books-sync');
// creates 30 book IDs
const booksIds = Array.from({length: 30}, (_, i) => i + 1);
// creates 30 API links for each request
const urls = booksIds.map(bookId => `http://localhost:7777/books/read-later?bookId=${bookId}`);
for(let url of urls) {
const response = await fetch(url);
const json = await response.json();
console.log(json);
}
console.timeEnd('save-books-sync');
}
Run Code Online (Sandbox Code Playgroud)
运行时间:3712.40087890625 毫秒
尽管我们不会创建许多与服务器的请求连接,但运行时本身就说明了一切。
代码:
async function saveAllBooksAtOnce() {
console.time('save-all-books')
const booksIds = Array.from({length: 30}, (_, i) => i + 1);
const url = `http://localhost:7777/books/read-later?all=1`;
const response = await fetch(url);
const json = await response.json();
console.timeEnd('save-all-books');
}
Run Code Online (Sandbox Code Playgroud)
运行时间:3486.71484375 毫秒
神奇的事情发生了,问题的解决方案是什么是最有效的请求方法。
在这里,我们提出了30 个并行的小请求,并取得了惊人的结果。
代码:
async function saveBooksParallel() {
console.time('save-books')
const booksIds = Array.from({length: 30}, (_, i) => i + 1);
const urls = booksIds.map(bookId => `http://localhost:7777/books/read-later?bookId=${bookId}`);
const promises = urls.map((url) =>
fetch(url).then((response) => response.json())
);
const data = await Promise.all(promises);
console.log(data);
console.timeEnd('save-books');
}
Run Code Online (Sandbox Code Playgroud)
在这个异步并行示例中,我使用了该Promise.all方法。
Promise.all() 方法将可迭代的 Promise 作为输入,并返回单个 Promise,该 Promise 解析为输入 Promise 结果的数组
运行时间:668.47705078125 毫秒
结果很清楚,发出这些多个请求的最有效方法是在异步并行中执行此操作。
更新:我按照@Iglesias Leonardo的请求删除了数据输出的console.log(),因为(大概)它需要大量资源。
这些是运行时结果:
更新结论: 运行时间几乎保持不变,从而反映了并行异步请求在速度上无法匹敌的现实
小智 10
选项 1 听起来不错,但在可扩展性方面存在很大问题。
选项 2 缓解了这种可扩展性问题,我们可以改进其设计:
客户端,通过 javascript,仅收集显示的书籍 ID 并通过 ajax 查询一次,以获取一系列稍后阅读的信息,仅适用于这 30 本书。通过这种方式,您仍然可以快速提供页面并请求一小组额外信息,一次使用单个 http 请求。
在服务器端,您可以进一步改进缓存每个用户稍后读取 id 的内存数组。
| 归档时间: |
|
| 查看次数: |
6541 次 |
| 最近记录: |