根据 firebase 管理值事件更改 Dom 元素

change Dom element based on firebase admin value events

我在 Servlet 中打印了一个简单的 HTML 页面。在这里,我设置了 firebase admin sdk 并为路径设置了值事件侦听器。

事件触发时,我希望更改 Div 元素并在那里显示结果。

编辑:侦听器确实在使用日志进行进一步测试。

但我仍然不知道如何反映 div 元素内部的变化,因为侦听器是异步的。这很可能是脚本无法正常工作的原因。

有人可以指导我应该做什么吗?代码如下:

 import java.io.IOException;
 import java.io.InputStream;
 import java.io.PrintWriter;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.Date;

 import javax.servlet.ServletException;
 import javax.servlet.annotation.WebServlet;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;

 import com.google.firebase.FirebaseApp;
 import com.google.firebase.FirebaseOptions;
 import com.google.firebase.auth.FirebaseCredentials;
 import com.google.firebase.database.DataSnapshot;
 import com.google.firebase.database.DatabaseError;
 import com.google.firebase.database.DatabaseReference;
 import com.google.firebase.database.FirebaseDatabase;
 import com.google.firebase.database.ValueEventListener;

 @WebServlet("/WebWaitlistViewServelet")
 public class WebWaitlistViewServelet extends HttpServlet {
private static final long serialVersionUID = 1L;

public WebWaitlistViewServelet() {
    super();
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    PrintWriter pw = response.getWriter();

    try {

        String cityName=request.getParameter("city");

        String restId = request.getParameter("restid");

        String userId = request.getParameter("userid");

        if(cityName == null || restId == null || userId == null){
            System.out.println("Error getting values");
            return;
        }else{
            System.out.println(cityName+" "+restId+" "+userId);
        }


        pw.println("<HTML>");

            pw.println("<HEAD>");

                pw.println("<script>");

                    pw.println("function changePosition(position){ document.getElementById(\"positionInList\").innerHTML = position };");

                    pw.println("function changeTimeTillTurn(timetillturn){ document.getElementById(\"timeTillTurn\").innerHTML = timetillturn };");

                    pw.println("function showTimeTillTurn(){ document.getElementById(\"timeDiv\").style.display = \"visible\" };");

                    pw.println("function hideTimeTillTurn(){ document.getElementById(\"timeDiv\").style.display = \"hidden\" };");

                pw.println("</script>");

            pw.println("</HEAD>");

            pw.println("<BODY>");

                pw.println("<DIV align=\"center\">");

                    pw.println("<B>Your position in the waitlist is:</B>");

                pw.println("</DIV><br/>");

                pw.println("<DIV id=\"positionInList\" align=\"center\" style=\"color:blue\">");

                    pw.println("Loading...");

                pw.println("</DIV><br/>");

                pw.println("<DIV id=\"timeDiv\" align=\"center\">");

                    pw.println("<B>Approximate time till your turn is: </B><span id=\"timeTillTurn\" style=\"color:blue\">Loading...</span>");

                pw.println("</DIV>");

            pw.println("<BODY>");

        pw.println("</HTML>");

        pw.flush();


        InputStream is = getServletContext().getResourceAsStream("/WEB-INF/firebaseauth/firebase_admin_sdk_key.json");

        // Initialize the app with a service account, granting admin privileges
        FirebaseOptions options = new FirebaseOptions.Builder()
            .setCredential(FirebaseCredentials.fromCertificate(is))
            .setDatabaseUrl("https://restaurantrepo.firebaseio.com")
            .build();
        try {
            FirebaseApp.initializeApp(options);
        } catch (Exception e) {
            //
        }



        // As an admin, the app has access to read and write all data, regardless of Security Rules
        DatabaseReference waitlistRef = FirebaseDatabase.getInstance().getReference().child(cityName).child(restId).child("waitlist");

        Comparator<WaitlistedPerson> sortComparator = new Comparator<WaitlistedPerson>() {
            @Override
            public int compare(WaitlistedPerson lhs, WaitlistedPerson rhs) {
                //sort ascending... the bigger the time entered, the later the person has joined... thus the higher the time entered the lower the position
                //on waitlist
                if(lhs.getTimeentered()<rhs.getTimeentered()){
                    //if time entered is lower, keep the person higher in the list
                    return -1;
                }else if(lhs.getTimeentered()==rhs.getTimeentered()){
                    //if the time entered is the same, there are two cases possible
                    //1.. one person is remotely entered and one has entered at the resto POS... in this case, give priority to POS entered user
                    //2.. both people have remotely entered ... in this case, give preference to the person with lowest userid (he/she started using our app earlier)
                    //
                    //cases that will never happen are
                    //1.. two people with same userid entered remotely at same time .. can't happen as a second entry simply overwrites the old entry
                    //2.. two people with same time entered at POS ... can't happen as the resto host can only enter one party at a time..
                    if(!lhs.isRemotelyEntered() && rhs.isRemotelyEntered()){
                        //Log.d("FragmentCreate","lhs userid "+lhs.getUserid()+" lhs remotelyentered "+lhs.isRemotelyEntered());
                        //Log.d("FragmentCreate","rhs userid "+rhs.getUserid()+" rhs remotelyentered "+rhs.isRemotelyEntered());
                        return -1;
                    }else if(lhs.isRemotelyEntered() && rhs.isRemotelyEntered()){
                        //return the lowest user id
                        //userid is of format Uxx ... so get the xx part begining from index 1 of the string and get the number
                        int lhsuserid = Integer.parseInt(lhs.getUserid().substring(1));
                        int rhsuserid = Integer.parseInt(rhs.getUserid().substring(1));

                        //Log.d("FragmentCreate"," The userids are lhsuserid "+lhsuserid+" rhsuserid"+rhsuserid);

                        //Do not get tempted to use String compareto function as this will give wrong results
                        // U11 will get priority over U4 in string compareto due to 1 being lexicographically smaller
                        //Thus never use lexicographical sorting ever.

                        //The user ids can never be equal as two remotely entered users will never have two entries (can't... it's impossible due to firebase)

                        if(lhsuserid<rhsuserid){
                            return  -1;
                        }else if(lhsuserid==rhsuserid){
                            //can never happen in real life... two remotely entered users can never have same id ever... just made for safeguard
                            return 0;
                        }else{
                            return 1;
                        }

                    }else if(!lhs.isRemotelyEntered() && !rhs.isRemotelyEntered()){
                        //both entered at POS and have same time
                        //can never happen in real life...
                        //made this just for testing scenarios in case i screw up and give wrong inputs
                        return 0;
                    }else{
                        //Log.d("FragmentCreate","lhs userid "+lhs.getUserid()+" lhs remotelyentered "+lhs.isRemotelyEntered());
                        //Log.d("FragmentCreate","rhs userid "+rhs.getUserid()+" rhs remotelyentered "+rhs.isRemotelyEntered());
                        return 1;
                    }
                }else{
                    return 1;
                }
            }
        };

        ArrayList<WaitlistedPerson> listOfPeople = new ArrayList<>();

        ValueEventListener eventListener = new ValueEventListener(){

            @Override
            public void onCancelled(DatabaseError error) {
                pw.println("<script>hideTimeTillTurn();</script>");
                pw.println("<script>changePosition('Sorry, some error occured');</script>");
                System.out.println("Sorry. some error occured");
            }

            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {

                int positionCounter=0;

                if(dataSnapshot.getChildrenCount()==1 || dataSnapshot.getChildrenCount() == 0 ){
                    //Log.d("FragmentCreate","This indicates that the restaurant probably closed down and removed all customers from the list");
                    pw.println("<script>hideTimeTillTurn();</script>");
                    pw.println("<script>changePosition('You are no longer in the waitlist');</script>");
                    System.out.println("You are no longer in the waitlist");
                }else{

                    if(dataSnapshot.hasChild(userId)){

                        double averageWaitTime=0.0d;

                        long timeEnteredInMillis=0;

                        listOfPeople.clear();

                        Iterable<DataSnapshot> peopleInList = dataSnapshot.getChildren();

                        for(DataSnapshot currentPerson : peopleInList){

                            if(currentPerson.getKey().equals("dummy")){
                                continue;
                            }

                            if(currentPerson.getKey().equals(userId)){
                                //This is our node.... break the loop and enjoy using the counter
                                averageWaitTime = currentPerson.child("averagewaittimeperparty").getValue(Double.class);
                                timeEnteredInMillis = currentPerson.child("timeentered").getValue(Long.class);
                                listOfPeople.add(new WaitlistedPerson(currentPerson));
                            }else{
                                listOfPeople.add(new WaitlistedPerson(currentPerson));
                            }

                        }

                        //sort the list using our custom comparator and the get the index

                        Collections.sort(listOfPeople,sortComparator);

                        //find the position of the user now

                        for(WaitlistedPerson person : listOfPeople){
                            ++positionCounter;
                            if(person.getUserid().equals(userId)){
                               break;
                            }
                        }

                        double timetillturn = Math.round(averageWaitTime * ((double)positionCounter));

                        long timeShouldComeAt = timeEnteredInMillis + (long)(timetillturn*60000);

                        Date timeWhenTurnArrives = new Date(timeShouldComeAt);

                        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");

                        pw.println("<script>showTimeTillTurn();</script>");
                        pw.println("<script>changePosition('"+positionCounter+"');</script>");
                        pw.println("<script>changeTimeTillTurn('"+sdf.format(timeWhenTurnArrives)+"');</script>");
                        System.out.println(positionCounter+" "+sdf.format(timeWhenTurnArrives));

                    }else{
                        pw.println("<script>hideTimeTillTurn();</script>");
                        pw.println("<script>changePosition('You are no longer in the waitlist');</script>");
                        System.out.println("You are no longer in the waitlist");

                    }

                }

            }

        };

        waitlistRef.addValueEventListener(eventListener);

    } catch (Exception e) {
        e.printStackTrace();
    }finally{
        try {
            pw.close();
        } catch (Exception e) {
            //do nothing here
        }
    }


}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    doGet(request, response);
}

}

使用 servlet,您的客户在向您的应用程序服务器发送新请求之前不会看到任何页面更新。您可以做的是让 ValueEventListener 更新内存中对象的状态。然后您的 servlet 可以在构造 HTML 输出时读取该对象的最新状态。

所以我设法使用 JSP 而不是 Servelet 解决了这个问题。

无论哪种情况,解决方案都是将所有逻辑转移到 JavaScript 函数。然后在 body load.

上调用上述函数
onload=callthefunction()

firebase 侦听器已从 java 转换为 JavaScript 版本:

on()
off()

这种方式需要调用ajax什么的,需要改变的元素可以直接从JavaScript

改变