javascript js异步等待使用缓存方法获取

plupiseo  于 2023-01-11  发布在  Java
关注(0)|答案(1)|浏览(138)

我必须向HTML页面上的js对象添加一个数据结构列表。我在服务器端有一个数据结构列表,每个结构由data-key标识。js函数循环data-keys的列表,该函数使用对应的data-keyasync_cache中一次获取一个结构。列表中可能有多个相同的data-keys
1.如果async_cachedata-key之前不具有data-structure,则它异步获取并将其添加到该高速缓存。
1.如果async_cache通过data-key具有data-structure,则它立即返回它。
1.如果X1 M11 N1 X已经请求获取X1 M12 N1 X,并且在数据到达之前具有对同一X1 M13 N1 X的另一请求,则它必须不复制该请求,而是等待直到数据到达。
到目前为止,我已经构造了下面的代码(作为讨论的例子)。实际的环境不能共享。

<?php 
    switch($_GET['--action'] ?? false){
        case 'data-structure':{
            $data_group = [
                'data-01' => ['a' => 'info-01', 'b' => 'extra-01'],
                'data-02' => ['a' => 'info-02', 'b' => 'extra-02'],
                'data-03' => ['a' => 'info-03', 'b' => 'extra-03'],
                'data-04' => ['a' => 'info-04', 'b' => 'extra-04'],
                'data-05' => ['a' => 'info-05', 'b' => 'extra-05'],
            ];
            if($data_struct = ($data_group[$_GET['key'] ?? false] ?? false)){
                \header('Content-Type: application/json');
                echo json_encode(['status'=> 'ok', 'data' => $data_struct], JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
                exit();
            } else {
                http_response_code(404);
                echo json_encode('Not Found', JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
                exit();
            }
        } break;
    }
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta key="viewport" content="width=device-width, initial-scale=1.0">
    <title>JS Async Data Buffer Experiment</title>
</head>
<body>
    <div class="container">
        
    </div>
    <script>
        xui = {};
        xui.async_cache = {
            async async_get_await(url = '', options = {}){
                // Default options are marked with *
                const response = await fetch(
                    url, 
                    {
                        method: 'GET', // *GET, POST, PUT, DELETE, etc.
                        mode: options.mode || 'same-origin', // no-cors, *cors, same-origin
                        cache: options.cache || 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
                        credentials: options.credintials || 'same-origin', // include, *same-origin, omit
                        redirect: options.redirect || 'follow', // manual, *follow, error
                        referrerPolicy: options.referrerPolicy || 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
                    }
                );
                
                return response.json(); // parses JSON response into native JavaScript objects;
            },
            get(action, key){
                if(key in this){
                    return new Promise((resolve, reject) => {
                        resolve(this[key]);
                    });
                } else {
                    return this.async_get_await(
                        `?--action=${action}&key=${key}`,
                    ).then((r) => {
                        this[key] = r.data;
                        return this[key];
                    });
                }
            },
        };
        
        window.addEventListener('DOMContentLoaded', function(){
            
            var list = [
                'data-01',
                'data-01',
                'data-02',
                'data-01',
                'data-03',
                'data-02',
                'data-04',
                'data-02',
                'data-01',
            ];
            
            list.forEach((key) => {
                console.log({key});
                xui.async_cache.get('data-structure', key).then((data) => {
                    console.log(data);
                });
            });
        });
        
    </script>
</body>
</html>

第1种和第2种情况已经解决了,但第3种情况是我遇到的问题。正如您所看到的,addEventListner中的代码在接收数据或事件循环启动之前一次性执行。因此,对同一个data-key发出了多个请求。
我正在寻找一个最低限度的方法。如果有一个编码功能在JS库没有使用第三方库-这将做得很好。
我还研究了Fetch-API上该高速缓存选项,但这不是一个解决方案。
谢谢!

shyt4zoc

shyt4zoc1#

感谢@Bergi我终于弄明白了!我重写了async_cache并继续简化...以下是我得到的结果(我还添加了一些测试按钮):

<?php 
    switch($_GET['--action'] ?? false){
        case 'data-structure':{
            $data_group = [
                'data-01' => ['a' => 'info-01', 'b' => 'extra-01'],
                'data-02' => ['a' => 'info-02', 'b' => 'extra-02'],
                'data-03' => ['a' => 'info-03', 'b' => 'extra-03'],
                'data-04' => ['a' => 'info-04', 'b' => 'extra-04'],
                'data-05' => ['a' => 'info-05', 'b' => 'extra-05'],
            ];
            if($data_struct = ($data_group[$_GET['key'] ?? false] ?? false)){
                \header('Content-Type: application/json');
                echo json_encode(['status'=> 'ok', 'data' => $data_struct], JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
                exit();
            } else {
                http_response_code(404);
                echo json_encode('Not Found', JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
                exit();
            }
        } break;
    }
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta key="viewport" content="width=device-width, initial-scale=1.0">
    <title>JS Async Data Cache Example</title>
</head>
<body>
    <div class="container">
        <button type="button" onclick="run()">Run</button> <br/>
        <button type="button" onclick="delete xui.async_cache['data-01']">Delete 01</button> <br/>
        <button type="button" onclick="delete xui.async_cache['data-02']">Delete 02</button> <br/>
        <button type="button" onclick="delete xui.async_cache['data-03']">Delete 03</button> <br/>
        <button type="button" onclick="delete xui.async_cache['data-04']">Delete 04</button> <br/>
        Look at the console for responses and check the network tab as well!
    </div>
    <script>
        xui = {};
        xui.async_cache = {
            get(key){
                return this[key] ?? (this[key] = (fetch(`?--action=data-structure&key=${key}`).then((response) => {
                    return response.json();
                })));
            }
        };

        function run(){
            
            var list = [
                'data-01',
                'data-01',
                'data-02',
                'data-01',
                'data-03',
                'data-02',
                'data-04',
                'data-02',
                'data-01',
            ];
            
            list.forEach((key) => {
                console.log({key});
                xui.async_cache.get(key).then((data) => {
                    console.log(data);
                });
            });
            
        }
        
        window.addEventListener('DOMContentLoaded', function(){
            run();
        });
        
    </script>
</body>
</html>

看起来我们可以利用promise中闭包的数据存储(或缓存),而且我们不需要await或async,至少在这个初级阶段是这样。

相关问题