博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
react mongodb_如何使用Socket.io,React,Node和MongoDB创建实时应用
阅读量:2523 次
发布时间:2019-05-11

本文共 16139 字,大约阅读时间需要 53 分钟。

react mongodb

Ever wondered how real time apps are built? Ever noticed the importance and use cases of real time applications?

有没有想过如何构建实时应用程序? 是否曾经注意到实时应用程序的重要性和用例?

If you are curious about the above questions and need an answer, then this blog post is for you.

如果您对以上问题感到好奇并需要答案,那么此博客文章适合您。

First, let’s identify a few use cases needing real time applications:

首先,让我们确定一些需要实时应用的用例:

  1. Getting location updates for your cab on a map of a cab booking application.

    在出租车预订应用程序的地图上获取出租车的位置更新。
  2. Getting new messages instantly on your favourite chatting application.

    在您最喜欢的聊天应用程序上立即获取新消息。
  3. Food order info update to the kitchen of your favourite restaurant.

    食物订单信息将更新到您最喜欢的餐厅的厨房。

These all are the common scenarios of our day to day lives where we can’t tolerate a delay in the updating of information and hence need real time communication.

这些都是我们日常生活中的常见情况,在这些情况下我们不能容忍信息更新的延迟,因此需要实时通信。

Technologies which can be used for realtime communication are:

其可以被用于实时通信的 技术是:

  1. Short Polling: AJAX, creates heavy traffic.

    短轮询 :AJAX,会造成大量流量。

  2. Long Polling: Like AJAX, but the server holds on the response until it has an update. After receiving it, the client sends another request, and needs additional header to be traversed back and forth causing additional overhead.

    长轮询 :与AJAX相似,但是服务器保留响应,直到更新为止。 客户端收到请求后,会发送另一个请求,并且需要来回遍历其他标头,从而导致额外的开销。

  3. Web Sockets: make it possible to open interactive communication between the client and server. One can send a request to the server and receive event driven responses without Polling the server for a reply, making web sockets a best choice for our use case.

    Web套接字 :可以打开客户端和服务器之间的交互式通信。 无需轮询服务器即可获得答复,就可以向服务器发送请求并接收事件驱动的响应,这使Web套接字成为我们用例的最佳选择

More in-depth info about the above three technologies can be read .

有关以上三种技术的更多详细信息,请参见 。

We will be learning to create a real time application by covering the following scenario.

我们将通过涵盖以下场景来学习创建实时应用程序。

Imagine you are sitting at your favourite restaurant and have a digital menu. You place the order and the kitchen gets updated regarding your order in real time. When the kitchen is done with the order, they update it in real time too.

想象一下,您坐在自己喜欢的餐厅里,并且有一个数字菜单。 您下订单后,厨房会实时更新您的订单。 当厨房处理完订单后,他们也会实时更新。

Features in detail:

详细功能:

  1. Place Order: Interface to select the quantity and place the order for a selected food item to the kitchen.

    下订单 :用于选择数量并将所选食物的订单下达到厨房的界面。

  2. Kitchen: Interface which can be opened across multiple kitchens and updates in real time the chefs and cooks regarding the total orders created and predicted quantity of food items, giving them the flexibility to update it. Also has a functionality to download the report in the form of an excel sheet.

    厨房 :可以在多个厨房中打开的界面,可以实时更新厨师和厨师关于已创建的总订单和预计食品数量的信息,从而使他们可以灵活地进行更新。 还具有以excel表格形式下载报告的功能。

  3. Change Predicted: Interface to update the predicted quantity of food items.

    更改预测值 :用于更新预测食品数量的界面。

A live demo of this scenario can be found .

可以在找到这种情况的现场演示

For better understanding, open it in different tabs/devices at the same time to see the data change in real time.

为了更好地理解,请同时在不同的选项卡/设备中打开它,以实时查看数据更改。

The source code is . Feel free to make something innovative/useful on top of it.

源代码在 。 随时在其上进行创新/实用。

So let’s get started.

因此,让我们开始吧。

技术栈: (Technology Stack:)

Frontend: React.js, Reactstrap, Socket.io

前端 :React.js,Reactstrap,Socket.io

Backend: Node.js (Express), MongoDB, Socket.io

后端 :Node.js(Express),MongoDB,Socket.io

资料夹结构: (Folder Structure:)

/*Go to the root directory in the source code and find out the below-mentioned files. This architecture helps in creating a big modular App.*/backend-my-app/ /* Backend code of the app */ server.js       /* Socket and backend code resides here*/ build/      /* Optional for deployment of Frontend Build */  package.json /* Backend dependency */ ...public/src/  /*      Frontend Sourcecode      */ global/      /*   Components getting used everywhere   */  header.css  header.js      main/             Kitchen.js  PlaceOrder.js  UpdatePredicted.js App.js   /* Routing logic and component assembly part */package.json /* Frontend dependency */  ............

源代码说明: (Explanation of source code:)

前端: (Frontend:)

git clone https://github.com/honey93/OrderKitchen.gitcd OrderKitchennpm installnpm start

Packages used:

使用的软件包:

  1. : Easy to use bootstrap4 components

    :易于使用的bootstrap4组件

  2. : Socket.io is a library that enables real-time, bidirectional and event-based communication between the browser and the server.

    是一个库,可在浏览器与服务器之间进行实时,双向和基于事件的通信。

  3. : Provides a client side generation of Excel (.xls) file from HTML table element.

    :从HTML表格元素提供客户端生成的Excel(.xls)文件。

  4. : DOM bindings for react router. It consists of many important components like BrowserRouter used when there is a server to handle dynamic request, Switch, Route, etc.

    :React DOM绑定。 它由许多重要组件组成,例如在有服务器处理动态请求,交换机,路由等时使用的BrowserRouter。

应用组件 (App Component)

Path: src/App.js

路径 :src / App.js

This component contains the main routing logic of the Frontend. This file is used in src/index.js inside the Browser Router Module. The below code demonstrates one of the approaches to keep your app modular.

该组件包含前端的主要路由逻辑。 该文件在浏览器路由器模块中的src / index.js中使用。 以下代码演示了保持应用模块化的方法之一。

import React, { Component } from "react";import "./App.css";import { Header } from "./global/header";import { Switch, Route } from "react-router-dom";import PlaceOrder from "./main/PlaceOrder";import UpdatePredicted from "./main/UpdatePredicted";import Kitchen from "./main/Kitchen";/*The 
component is the main part of React Router. Anywhere that you want to only render content based on the location’s pathname, you should use a
element. *//* The Route component expects a path prop, which is a string that describes the pathname that the route matches *//* The
will iterate over routes and only render the first one that matches the current pathname */class App extends Component { render() { return (
); }}export default App;

标头组件 (Header Component)

Path: src/global/header.js

路径 :src / global / header.js

This component will be common and used across the sections like Place Order, Change Predicted, Kitchen. This approach helps avoid code duplication and keeps the application modular.

该组件是通用组件,将在下订单,预测更改,厨房等部分中使用。 这种方法有助于避免代码重复,并使应用程序保持模块化。

import React, { Component } from "react";import { NavLink } from "react-router-dom";import socketIOClient from "socket.io-client";import "./header.css";// The Header creates links that can be used to navigate// between routes.var socket;class Header extends Component {/* Creating a Socket client and exporting it at the end to be used across the Place Order, Kitchen, etc components*/  constructor() {    super();    this.state = {      endpoint: 'http://localhost:3001/'    };socket = socketIOClient(this.state.endpoint);  }render() {    return (      
); }}export { Header, socket };

厨房组件 (Kitchen Component)

Path: src/main/Kitchen.js

路径 :src / main / Kitchen.js

The Kitchen Screen UI logic and html code resides in this component:

Kitchen Screen UI逻辑和html代码位于此组件中:

import React, { Component } from "react";import { Button, Table, Container } from "reactstrap";import { socket } from "../global/header";import ReactHTMLTableToExcel from "react-html-table-to-excel";class Kitchen extends Component {  constructor() {    super();    this.state = {      food_data: []      // this is where we are connecting to with sockets,    };  }getData = foodItems => {    console.log(foodItems);    this.setState({ food_data: foodItems });  };changeData = () => socket.emit("initial_data");/*As soon as the component gets mounted ie in componentDidMount method, firing the initial_data event to get the data to initialize the Kitchen Dashboard *//* Adding change_data listener for listening to any changes made by Place Order and Predicted Order components*/ componentDidMount() {    var state_current = this;    socket.emit("initial_data");    socket.on("get_data", this.getData);    socket.on("change_data", this.changeData);  }/* Removing the listener before unmounting the component in order to avoid addition of multiple listener at the time revisit*/componentWillUnmount() {    socket.off("get_data");    socket.off("change_data");  }/* When Done gets clicked, this function is called and mark_done event gets emitted which gets listened on the backend explained later on*/markDone = id => {    // console.log(predicted_details);    socket.emit("mark_done", id);  };getFoodData() {    return this.state.food_data.map(food => {      return (                   {food.name}            {food.ordQty}            {food.prodQty}            {food.predQty}                                               );    });  }render() {    return (      

Kitchen Area

{this.getFoodData()}
Name Quantity Created Till Now Predicted Status
); }}export default Kitchen;

下订单组件 (Place Order Component)

Path: src/main/PlaceOrder.js

路径 :src / main / PlaceOrder.js

import React, { Component } from "react";import { Button, Table, Container } from "reactstrap";import { socket } from "../global/header";class PlaceOrder extends Component {  constructor() {    super();    this.state = {      food_data: []      // this is where we are connecting to with sockets,    };  }getData = foodItems => {    console.log(foodItems);    foodItems = foodItems.map(food => {      food.order = 0;return food;    });    this.setState({ food_data: foodItems });  };componentDidMount() {    socket.emit("initial_data");    var state_current = this;    socket.on("get_data", state_current.getData);  }componentWillUnmount() {    socket.off("get_data", this.getData);  }//Function to place the order.sendOrder = id => {    var order_details;    this.state.food_data.map(food => {      if (food._id == id) {        order_details = food;      }      return food;    });    console.log(order_details);    socket.emit("putOrder", order_details);    var new_array = this.state.food_data.map(food => {      food.order = 0;      return food;    });    this.setState({ food_data: new_array });  };// Changing the quantity in the state which is emitted to the backend at the time of placing the order.changeQuantity = (event, foodid) => {    if (parseInt(event.target.value) < 0) {      event.target.value = 0;    }    var new_array = this.state.food_data.map(food => {      if (food._id == foodid) {        food.order = parseInt(event.target.value);      }      return food;    });    this.setState({ food_data: new_array });  };// To get the initial datagetFoodData() {    return this.state.food_data.map(food => {      return (                   {food.name}                        this.changeQuantity(e, food._id)}              value={food.order}              type="number"              placeholder="Quantity"            />                                                        );    });  }render() {    return (      

Order Menu

{this.getFoodData()}
Product Quantity Order
); }}export default PlaceOrder;

One more section called Update Predicted Path: src/main/UpdatePredicted.js similar to above section is there in the code repository.

代码存储库中还有一个类似于“更新预测的路径”的部分:src / main / UpdatePredicted.js与上面的部分相似。

后端 (Backend)

Starting the Backend:

启动后端:

cd backend-my-appnpm installnode server.js

Packages used:

使用的软件包:

  1. : A tiny layer that provides simple yet substantial usability improvements for MongoDB usage within Node.JS.

    :一个很小的层,它为Node.JS中的MongoDB使用提供了简单而实质性的可用性改进。

  2. : Socket.io is a library that enables real-time, bidirectional and event-based communication between the browser and the server.

    是一个库,可在浏览器和服务器之间进行实时,双向和基于事件的通信。

3. : Fast, minimalist web framework for .

3. : 快速,简约的Web框架。

主要代号 (Main Code)

Path: backend-my-app/server.js

路径 :backend-my-app / server.js

const express = require("express");const http = require("http");const socketIO = require("socket.io");// Connection string of MongoDb database hosted on Mlab or locallyvar connection_string = "**********";// Collection name should be "FoodItems", only one collection as of now.// Document format should be as mentioned below, at least one such document:// {//     "_id": {//         "$oid": "5c0a1bdfe7179a6ca0844567"//     },//     "name": "Veg Roll",//     "predQty": 100,//     "prodQty": 295,//     "ordQty": 1// }const db = require("monk")(connection_string);const collection_foodItems = db.get("FoodItems");// our localhost portconst port = process.env.PORT || 3000;const app = express();// our server instanceconst server = http.createServer(app);// This creates our socket using the instance of the serverconst io = socketIO(server);io.on("connection", socket => {//  console.log("New client connected" + socket.id);  //console.log(socket);// Returning the initial data of food menu from FoodItems collection  socket.on("initial_data", () => {    collection_foodItems.find({}).then(docs => {      io.sockets.emit("get_data", docs);    });  });// Placing the order, gets called from /src/main/PlaceOrder.js of Frontend  socket.on("putOrder", order => {    collection_foodItems      .update({ _id: order._id }, { $inc: { ordQty: order.order } })      .then(updatedDoc => {        // Emitting event to update the Kitchen opened across the devices with the realtime order values        io.sockets.emit("change_data");      });  });// Order completion, gets called from /src/main/Kitchen.js  socket.on("mark_done", id => {    collection_foodItems      .update({ _id: id }, { $inc: { ordQty: -1, prodQty: 1 } })      .then(updatedDoc => {        //Updating the different Kitchen area with the current Status.        io.sockets.emit("change_data");      });  });// Functionality to change the predicted quantity value, called from /src/main/UpdatePredicted.js  socket.on("ChangePred", predicted_data => {    collection_foodItems      .update(        { _id: predicted_data._id },        { $set: { predQty: predicted_data.predQty } }      )      .then(updatedDoc => {        // Socket event to update the Predicted quantity across the Kitchen        io.sockets.emit("change_data");      });  });// disconnect is fired when a client leaves the server  socket.on("disconnect", () => {    console.log("user disconnected");  });});/* Below mentioned steps are performed to return the Frontend build of create-react-app from build folder of backend Comment it out if running locally*/app.use(express.static("build"));app.use("/kitchen", express.static("build"));app.use("/updatepredicted", express.static("build"));server.listen(port, () => console.log(`Listening on port ${port}`));

Database: MongoDB

数据库 :MongoDB

: Database as a service for MongoDB

:数据库作为MongoDB的服务

Collection Name: FoodItems

馆藏名称 :FoodItems

Document format: At least one document is needed in the FoodItems collection with the below mentioned format.

文件格式 :在FoodItems集合中,至少需要一个具有以下格式的文件。

{"name": "Veg Roll",  // Food Name"predQty": 100,  // Predicted Quantity"prodQty": 295,  // Produced Quantity"ordQty": 1   // Total Order Quantity}

Hope you got the understanding of how to create a modular real time app using the trending MERN stack. If you found it helpful clap below, give stars to the project and share with your friends too.

希望您了解如何使用趋势不断的MERN堆栈创建模块化实时应用。 如果您发现以下有用的拍手 ,请为项目 星标 ,并与您的朋友分享。

翻译自:

react mongodb

转载地址:http://sfwzd.baihongyu.com/

你可能感兴趣的文章
第2天线性表链式存储
查看>>
python自动化测试-D11-学习笔记之一(yaml文件,ddt)
查看>>
mysql存储过程使用游标循环插入数据
查看>>
Ubuntu 12.04 添加新用户并启用root登录
查看>>
20145309信息安全系统设计基础第9周学习总结上
查看>>
c# 字段、属性get set
查看>>
td内容超出隐藏
查看>>
Spring CommonsMultipartResolver 上传文件
查看>>
Settings app简单学习记录
查看>>
SQLAlchemy
查看>>
多线程
查看>>
使用缓存的9大误区(下)转载
查看>>
appium键值对的应用
查看>>
MyEclipse 8.X 通用算法
查看>>
selenium.Phantomjs设置浏览器请求头
查看>>
分布式数据库如何选择,几种分布式数据库优缺点一览
查看>>
BZOJ 4443: 小凸玩矩阵【二分图】
查看>>
苹果 OS X制作u盘启动盘
查看>>
Jquery便利对象
查看>>
MVC: Connection String
查看>>