评级系统 javascript 不会将结果发送到 Firebase

Rating system javascript will not send results to firebase

本文关键字:结果 Firebase 系统 javascript      更新时间:2023-09-26

我有一个应该是一个有效的脚本,致力于根据其值(即 1/5、2/5、3/5 等)推送评级。但是脚本根本不与火力基地通信。我的javascript是否有问题,这会阻止输入的值按照指示发送到Firebase?这是所有必要的代码。此外,在文档的头部还有一个指向 firebase 的链接.js。

(function() {
    var firebaseUrl = "https://myFirebase.firebaseIO.com/rating";
    var itemId = (rootRef).child;
    var rootRef = new Firebase(firebaseUrl);  // Reference the Firebase location
    var itemRef = rootRef.child("items").child(itemId);     //Define itemRef as the variable for itemId in firebase
    var star = $('.rating');
    var numRatings;
        star.click(function() {     //Watch out for rating1 inside of the website and grab its value. i.e. 1, 2, 3, 4, or 5
            itemRef.child("ratings").child("numRatings").set(star.val());   //Set ratings inside of Firebase with values such as 1, 2, 3, 4, and 5, under items such as item1, item2, item3, etc... 
        });
    var cumulativeRating;
    var averageRating;
    itemRef.child("ratings").on("value", function(ratingsSnapshot) {
        var ratingsData = ratingsSnapshot.val();
        numRatings = ratingsData.numRatings;
        cumulativeRating = ratingsData.cumulativeRating;
        averageRating = cumulativeRating / numRatings;
    });
})();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!--Rating system begin-->
    <div class="rating">
        <div class="starRating">
            <div>
                <div>
                    <div>
                        <div>
                        <input id="rating1" class="rating" type="radio" name="rating" value="1">
                        <label for="rating1"><span>1</span></label>
                        </div>
                    <input id="rating2" class="rating" type="radio" name="rating" value="2">
                    <label for="rating2"><span>2</span></label>
                    </div>
                <input id="rating3" class="rating" type="radio" name="rating" value="3">
                <label for="rating3"><span>3</span></label>
                </div>
            <input id="rating4" class="rating" type="radio" name="rating" value="4">
            <label for="rating4"><span>4</span></label>
            </div>
        <input id="rating5" class="rating" type="radio" name="rating" value="5">
        <label for="rating5"><span>5</span></label>
        </div>
                <h3 class="ratingtext">Rated 4/5 by 103 users</h3>   
                <!--Rating system end-->

你的代码中有很多小错误。我将向您介绍其中的一些。但是,请不要只是复制代码,而是花时间了解我实际上是如何解决这些问题的。您的第一个目标应该是能够调试自己的代码以摆脱这些更简单的错误。

好的,我会写两个问题。可能还有更多,但这已经需要足够的时间。

  1. 处理 Firebase 中尚无数据的情况
  2. 获取单击的单选按钮的值

处理 Firebase 中尚无数据的情况

当我将您的代码粘贴到 jsbin 中时发生的第一件事是它会将其记录到 devtools 中的 JavaScript 控制台(您可以使用 F12 获得这些内容,并且在开发时应始终保持打开状态):

未捕获的类型错误: 无法读取 null 的属性"numRatings"

这是现代 JavaScript 版本的空指针异常,是由于您.numRatings nullundefined的东西。幸运的是,你只有一个地方.numRatings

itemRef.child("ratings").on("value", function(ratingsSnapshot) {
    var ratingsData = ratingsSnapshot.val();
    numRatings = ratingsData.numRatings;
    cumulativeRating = ratingsData.cumulativeRating;
    averageRating = cumulativeRating / numRatings;
});

所以看起来ratingsData没有价值,这确实发生在项目第一次获得评级时。在这种情况下,Firebase 将使用 null(或 undefined)触发value事件。

处理起来很简单:

itemRef.child("ratings").on("value", function(ratingsSnapshot) {
    var ratingsData = ratingsSnapshot.val();
    if (ratingsData) {
        numRatings = ratingsData.numRatings;
        cumulativeRating = ratingsData.cumulativeRating;
        averageRating = cumulativeRating / numRatings;
    }
});

在实际实现中,您可能希望向该if添加一个else,并显示还没有/没有足够的评级。

获取单击的单选按钮的值

将点击的值传递给 Firebase 的代码段如下:

var star = $('.rating');
star.click(function() {
    itemRef.child("ratings").child("numRatings").set(star.val());
});

我做的第一件事是在其中添加一个日志记录语句,以查看单击是否通过代码:

var star = $('.rating');
star.click(function() {
    console.log('click');
    itemRef.child("ratings").child("numRatings").set(star.val());
});

当我现在单击单选按钮时,它会记录click.所以看起来连接正确。下一步,我经常会放一个JavaScript debugger语句而不是console.log,但这次决定不这样做。

我做的下一个技巧是设置一个简单的Firebase记录器,以显示更改是否通过Firebase:

 new Firebase('https://you.firebaseIO.com/rating').on('value', function(s) { console.log(JSON.stringify(s.val())); })

您可以将其添加到脚本顶层的任何位置。我最常将其添加到Chrome开发工具的控制台中。每次 Firebase 的值发生变化时,它都会记录如下内容:

{"items":{"42":{"ratings":{"numRatings":"3"}}}}

或者这就是它应该做的,但在你的原始脚本中它从来没有这样做过。因此,我们进入了点击处理程序,但该值没有进入Firebase。

仔细观察会发现一些奇怪的事情:

var star = $('.rating');
star.click(function() {
    itemRef.child("ratings").child("numRatings").set(star.val());
});

您可以使用此代码段第一行中的变量star指向所有评分元素。但是在点击处理程序中,你star.val(),这意味着你希望它引用一个评级元素:被点击的那个。

此处简要说明变量名称:您可以通过对包含所有评级元素的变量使用单数star来设置此错误。我将这个变量命名为stars,以表明它包含多颗星。这样,当您键入时,您可以更容易看到stars.val()闻起来的东西。

我不是jQuery专家,但是快速谷歌jQuery的点击方法的文档似乎表明你可以this访问点击的元素。所以代码段需要:

var star = $('.rating');
star.click(function() {
    itemRef.child("ratings").child("numRatings").set($this).val());
});

有了这个,我的Firebase JSON记录器开始喷出数据:

{"items":{"42":{"ratings":{"numRatings":"3"}}}}

这些值现在已进入Firebase!

从问题中消除技术

请注意,这最后一项更改与 Firebase 无关。如果您尝试提醒该值,也会发生这种情况:

var star = $('.rating');
star.click(function() {
    alert(star.val());
});

这是调试问题(或创建 MCVE)时的关键点:尝试从问题中删除尽可能多的技术。通过从这个微小的代码片段中删除Firebase,问题从"为什么我的星级评分没有进入Firebase?"到"为什么这个代码片段不显示我点击的星级值?"或者一旦你掌握了它"我如何获得我点击的元素的值?"。最后一个问题是你可以输入谷歌并期望得到一个不错的结果,因为你不是第一个为此苦苦挣扎的人。试图在Firebase上建立星级评级系统的人数要少得多。

最后

正如我已经说过的,你的脚本仍然有问题。例如:每次点击单选按钮都会通过我的Firebase JSON记录器生成一对行:

{"items":{"42":{"ratings":{"numRatings":"3"}}}}
{"items":{"42":{"ratings":{"numRatings":""}}}}

因此,每次我单击单选按钮时,它似乎都会触发Firebase中的两个更改,第二个更改撤消了第一个更改的工作。我很确定我能弄清楚为什么会发生这种情况。但我希望通过上面的课程,您将能够自己解决这个问题。

我的最终脚本:

(function() {
    var firebaseUrl = "https://your.firebaseio.com/rating";
    var itemId = 42; // TODO: look up Id of the actual item
    var rootRef = new Firebase(firebaseUrl);
    var itemRef = rootRef.child("items").child(itemId);
    var star = $('.rating');
    var numRatings;
    star.click(function() {
        itemRef.child("ratings").child("numRatings").set($(this).val());
    });
    var cumulativeRating;
    var averageRating;
    itemRef.child("ratings").on("value", function(ratingsSnapshot) {
        var ratingsData = ratingsSnapshot.val();
        if (ratingsData) {
            numRatings = ratingsData.numRatings;
            cumulativeRating = ratingsData.cumulativeRating;
            averageRating = cumulativeRating / numRatings;
        }
    });
})();

它也在jsbin上,我在那里进行了调试:http://jsbin.com/lekifefuce/1/edit?js,output

是否已更新安全规则?

在 Firebase 中(链接参考),转到规则并添加感兴趣的数组或对象(复制教程中的示例 ovjects)

例如,将评级的读写设置为 true