【问题标题】:Knockout.js "visible" calling async function - not workingKnockout.js“可见”调用异步函数 - 不工作
【发布时间】:2017-02-02 14:20:00
【问题描述】:

我一直在尝试理解 async、promise 等,并且我认为我对它有了基本的了解,但我没有得到我期望的结果。

我有一个 HTML 表格,包含以下内容:

<table data-bind="visible: viewPrincipal()">

viewPrincipal() 是一个应该返回 true 或 false 的函数。如果 viewPrincipal() 只包含 return false 或 return true,这在最基本的级别上确实有效。但我想做的是调用一个异步函数来从那里获取真值或假值。

function viewPrincipal() {
  console.log("Seeing if person is in principal group");
  return IsCurrentUserMemberOfGroup("Principal Members", function (isCurrentUserInGroup) {
    console.log(isCurrentUserInGroup);
    return isCurrentUserInGroup;
  });
}

console.log 可以正常工作,并按照我的预期返回 true 或 false。但我希望父 viewPrincipal() 函数返回该 true 或 false 值,而我得到的只是“未定义”。

我明白为什么会发生这种情况 - IsCurrentUserMemberOfGroup() 函数需要一些时间才能完成 - 但我不知道如何解决它。我知道如何将函数链接在一起,但是当我尝试使用诸如 knockout.js 之类的东西来确定表是否应该可见时,我不知道如何链接。

谁能帮忙?

【问题讨论】:

    标签: javascript asynchronous knockout.js


    【解决方案1】:

    最好的方法是使用 observable bool,让你的异步函数改变它的值。让双向绑定的魔力完成其余的工作。

    例如:JSFIDDLE

    function vm() {
        this.viewPrincipal = ko.observable(false);
    };
    
    var vm = new vm();
    ko.applyBindings(vm);
    
    function fakeAsync() {
        setTimeout(() => {
            vm.viewPrincipal(true);
        }, 1500);
    }
    fakeAsync();
    

    【讨论】:

    • 谢谢!这真的帮助我弄清楚我应该做什么,现在我可以按照我的意愿工作。
    【解决方案2】:

    我对你的方法有点迷茫,但我会尽力提供帮助。

    首先,请三思你是否真的要在客户端实现访问控制。如果用户没有足够的权限,简单地隐藏一个元素是非常危险的,因为(可能)敏感内容仍然存在于 DOM 中,它仍然被下载,你所做的只是不显示它。即使是新手黑客也能找到一种方法来显示它 - 如果没有别的办法,他可以使用 F12 工具简单地查看它。

    第二,函数的三重嵌入真的有必要吗?您有一个最外层的函数,它调用一个函数,该函数又调用提供的回调。您可以使用computed observables 来解决这个问题:

    function viewModel() {
        var self = this;
    
        var serverData = ko.observable(null);
        this.viewPrincipal = ko.computed(function() {
            var srvDataUnwrapped = serverData();    // access the inner value
    
            if (!srvDataUnwrapped) {
                return false;
            }
    
            // Do your decision logic here...
    
            // return false by default
            return false;
        });
    
        // Load the permission details from the server, this will set
        // a variable that the viewPrincipal depends on, this will allow
        // Knockout to use its dependency tracking magic and listen for changes.
        (function() {
            $.ajax(url, {
                // other config
                success: function (data) {
                    serverData(data);
                }
            );
        })();
    };
    
    var vm = new viewModel();
    

    然后在你看来:

    <table data-bind="visible: viewPrincipal">
    

    注意这里缺少(),它是observable,所以Knockout会知道如何使用它。

    如果添加到现有代码中看起来过于复杂,那么您可以简单地定义一个 observable,并在回调中设置它的值:

    function viewModel() {
        // other stuff ...
        this.viewPrincipal = ko.observable(false);
    
        // Call this wherever it fits your requirements, perhaps in an init function.
        function checkPrincipal() {
            IsCurrentUserMemberOfGroup("Principal Members", function (isCurrentUserInGroup) {
                viewPrincipal(isCurrentUserInGroup);
            });
        };
    };
    

    使用这种方法,标记将与前一种相同,即没有括号:

    <table data-bind="visible: viewPrincipal">
    

    这样做只会在你传递给IsCurrentUserMemberOfGroup的回调中设置一个observable的内部值,并且因为Knockout能够跟踪observables的变化,所以值的变化将反映在 UI 中。

    希望对您有所帮助。

    【讨论】:

    • 谢谢!这与此处的其他评论一起,对让我理解整个事情非常有帮助。我意识到存在一些安全漏洞,但(对我来说幸运的是)这种更改的要求不是对大多数人隐藏某些数据,而是让大多数人的表单更小更短。我现在很好。
    猜你喜欢
    • 2020-07-13
    • 1970-01-01
    • 2019-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-25
    • 1970-01-01
    相关资源
    最近更新 更多