标签:根据 ons code sel write orm pwd 本地 pytho
express、socket.io
var express = require(‘express‘);
var app = express();
var http = require(‘http‘);
//创建一个服务器
var server = http.createServer(app);
//监听端口
var port = normalizePort(process.env.PORT || ‘3000‘);
server.listen(port);
app.set(‘views‘, path.join(__dirname, ‘views‘));
//服务器端引入socket.io
var io = require(‘socket.io‘).listen(server);
io.on(‘connection‘, function(socket){
socket.on(‘message‘, function () { });
socket.on(‘disconnect‘, function(){...});
});
//客户端引入socket
var socket = io();
socket.on(‘connect‘, function () {
socket.send(‘hi‘);
socket.on(‘message‘, function (msg) {
// my msg
});
});
{from:‘Client A‘, to:‘Client B‘, body: ‘hello‘}
的数据给 Server。// send to current request socket client
// 发送一个请求的当前请求的socket客户端
socket.emit(‘message‘, "this is a test");
// sending to all clients except sender
// 广播消息,不包括当前的发送者
socket.broadcast.emit(‘message‘, "this is a test");
// sending to all clients, include sender
// 发送消息给所有客户端,包括发送者
io.sockets.emit(‘hi‘, ‘everyone‘);
io.emit(‘hi‘, ‘everyone‘); // 写的简单点:
// sending to all clients in ‘room1‘ room except sender
// 给房间room1的所有客户端发送消息,不包括发送者
socket.broadcast.to(‘room1‘).emit(‘message‘, ‘hello‘);
// sending to all clients in ‘room1‘ room(channel), include sender
// 给房间room1的所有客户端发送消息,包括发送者
io.sockets.in(‘room1‘).emit(‘message‘, ‘hello‘);
// sending to individual socketid
// 给单个用户socketId发送消息
io.sockets.socket(socketId).emit(‘message‘, ‘for your eyes only‘);
io.sockets.on(‘connection‘, function (socket) {
socket.on(‘set nickname‘, function (name) {
socket.set(‘nickname‘, name, function () {
socket.emit(‘ready‘);
});
});
socket.on(‘msg‘, function () {
socket.get(‘nickname‘, function (err, name) {
console.log(‘Chat message by ‘, name);
});
});
});
io.on(‘connection‘, function(socket){
//加入房间
socket.join(‘some room‘);
//用to或者in是一样的,用emit来给房间激发一个事件
io.to(‘some room‘).emit(‘some event‘):
//socket.leave(‘some room‘);
});
io.on(‘disconnection‘, function(socket){
//一旦disconneted,那么会自动离开房间
...
});
var onlineList = [];
onlineList.push(uid);
onlineList.indexOf(uid)
index = onlineList.indexOf(uid) //找到对应的下标
onlineList.splice(index,1) //删除index到index+1的数据,也就是删除下标为index的数据
var userSchema = new Schema({
username: String,
password: String,
imgUrl: String,
meta: {
updateAt: {type:Date, default: Date.now()},
createAt: {type:Date, default: Date.now()}
}
});
ObjectId
,设置引用ref为User
var mongoose = require(‘../db‘);
var Schema = mongoose.Schema;
var ObjectId = Schema.Types.ObjectId;
var friendSchema = new Schema({
uid: {type:ObjectId, ref:‘User‘},
fid: {type:ObjectId, ref:‘User‘},
meta: {
updateAt: {type:Date, default: Date.now()},
createAt: {type:Date, default: Date.now()}
}
});
from
和to
两个对象uid
var messageSchema = new Schema({
uid: {type:ObjectId, ref:‘User‘},//用户
from: {type:ObjectId, ref:‘User‘},//发送给谁
to: {type:ObjectId, ref:‘User‘},//谁接收
msg: String,
type: Number,//已读1 or 未读0
meta: {
updateAt: {type:Date, default: Date.now()},
createAt: {type:Date, default: Date.now()}
}
});
$("body").on(‘click‘, ‘#registerBtn‘, doRegister);
registerBtn
的按钮,执行doRegister
函数ajax是一种异步的请求,当用户每次输入一定的值,服务器都会把这个值传递过来
$("#usr").val()
--用jquery的方式获取id
为usr
的表单的值
$("#userThumb").attr("src")
--用jquery的方式获取id为userThumb
的属性src
的值,获取图片的路径
JSON.stringify
是将传递过来的数据转换为JSON格式
如果成功,那么success,执行后面的function()
;
$.cookie(‘username‘, result.data.username, {expires:30});
是利用jquery.cookie.js将数据存放到cookie
里面
function doRegister() {
$.ajax({
type: "POST", //方式post
url: "/register", //路径register
contentType: "application/json",
dataType: "json", //数据类型json格式
data: JSON.stringify({
‘usr‘: $("#usr").val(), //用户名
‘pwd‘: $("#pwd").val(), //密码
‘imgUrl‘: $("#userThumb").attr("src") //图片
}),
success: function(result) {
if (result.code == 99) { //失败弹出错误信息
console.log("注册失败")
} else { //成功就将输入的数据作为cookies存入
console.log("注册成功");
console.log(result.data);
$.cookie(‘username‘, result.data.username, {expires:30});
$.cookie(‘password‘, result.data.password, {expires:30});
$.cookie(‘imgUrl‘, result.data.imgUrl, {expires:30});
$.cookie(‘id‘, result.data._id, {expires:30});
location.href = "/webchat"; //跳转到聊天界面
}
}
})
}
var urlRegister = "/register";
2.将上面的一段代码提炼出骨干
function postData(url, data, cb) {
var promise = $.ajax({
type: "post",
url: url, //传递过来的post路径
dataType: "json",
contentType: "application/json",
data:data //传递过来的data
});
promise.done(cb); //执行cb回调函数
}
3.将数据转换为JSON格式,传递参数到postData()
,执行函数
var jsonData = JSON.stringify({
‘usr‘: $("#usr").val(), //用户名
‘pwd‘: $("#pwd").val(), //密码
‘imgUrl‘: $("#userThumb").attr("src")
});
postData(urlRegister, jsonData, cbRegister);
4.cbRegster()函数
function cbRegister(result) {
console.log(result);
if (result.code == 99) { //失败弹出错误信息
console.log("注册失败")
} else { //成功就将输入的数据作为cookies存入
console.log("注册成功");
console.log(result.data);
$.cookie(‘username‘, result.data.username, {expires:30});
$.cookie(‘password‘, result.data.password, {expires:30});
$.cookie(‘imgUrl‘, result.data.imgUrl, {expires:30});
$.cookie(‘id‘, result.data._id, {expires:30});
location.href = "/webchat"; //跳转到聊天界面
}
}
$("body").on(‘change‘, ‘#uploadFile‘, preUpload);
$("body").on(‘click‘, ‘#UploadBtn‘, doUpload);
POST
post
路径设置为/uploadImage
form
userThumb
的src
属性设置为传递过来的datafunction doUpload() {
//取出上传过来的文件
var file = $("#uploadFile")[0].files[0];
//与普通的Ajax相比,使用FormData的最大优点就是可以异步上传二进制文件。
var form = new FormData();
form.append("file", file);
$.ajax({
url: "/uploadImg", //路径设置为uploadImage
type: "POST",
data: form, //数据格式为form
async: true,
processData: false,
contentType: false,
success: function(result) {
startReq = false;
if (result.code == 0) {
//将id为userThumb的src属性设置为传递过来的data
$("#userThumb").attr("src", result.data);
}
}
});
}
npm install --save-dev formidable
var formidable = require(‘formidable‘);
post
到/uploadImg
var form = new formidable.IncomingForm();
新建一个form
form.uploadDir = "./public/thumb";
设置文件存放的位置,自己事先定义好用来存放图片的文件夹router.post(‘/uploadImg‘, function(req, res, next) {
var form = new formidable.IncomingForm();
var path = "";
var fields = [];
form.encoding = ‘utf-8‘;
form.uploadDir = "./public/thumb";//存放文件的位置
form.keepExtensions = true;
form.maxFieldsSize = 30000 * 1024 * 1024;
var uploadprogress = 0;
console.log("start:upload----"+uploadprogress); //开始上传
form.parse(req);
form.on(‘field‘, function(field, value) {
console.log(field + ":" + value);
})
.on(‘file‘, function(field, file) {
path = ‘\\‘ + file.path; //获取文件的本地路径
})
.on(‘progress‘, function(bytesReceived, bytesExpected) {
uploadprogress = (bytesReceived / bytesExpected * 100).toFixed(0);
console.log("upload----"+ uploadprogress); //上传中
})
.on(‘end‘, function() {
console.log(‘-> upload done\n‘); //上传结束
entries.code = 0;
entries.data = path; //将路径赋给data
res.writeHead(200, {
‘content-type‘: ‘text/json‘
});
res.end(JSON.stringify(entries)); //将entries转换为JSON格式
})
.on("err",function(err){ //发生错误
var callback="<script>alert(‘"+err+"‘);</script>";
res.end(callback);
})
.on("abort",function(){ //中断
var callback="<script>alert(‘"+ttt+"‘);</script>";
res.end(callback);
});
});
router.post(‘/register‘, function(req, res, next) {
//添加用户
dbHelper.addUser(req.body, function (success, doc) {
res.send(doc);
})
});
exports.addUser = function(data, cb) {
var user = new User({
username: data.usr,
password: data.pwd,
imgUrl: data.imgUrl
});
user.save(function(err, doc) {
if (err) {
cb(false, err);
} else {
cb(true, entries);
}
})
};
这样整个上传的逻辑就已经写完了,接下来是添加一个朋友,和上面的做法一致。
唯一不同的是,我们在添加朋友的时候,一般都是相互之间都成为朋友的,所以在新建的时候要同时新建两个user
var friend_me = new Friend({
uid: data.uid,//自己的id
fid: data.fid
});
var friend_frd= new Friend({
uid: data.fid,//朋友的id
fid: data.uid
});
保存也需要同时保存两个新的对象
这里采用的是async的并行parallel操作,async的引入是通过var async = require(‘async‘);
async.parallel({
one: function(callback) {
//保存自己
friend_me.save(function(err, doc) {
callback(null, doc);
})
},
two: function(callback) {
//保存朋友
friend_frd.save(function(err, doc) {
callback(null, doc);
})
}
}, function(err, results) {
// results is now equals to: {one: 1, two: 2}
cb(true, entries);
});
消息的传递也需要同时创建两个消息,一个用来发给自己,另一个是发给朋友,保存的方式和朋友一致
var message_me = new Message({
uid: data.uid, //自己
from: data.from,
to: data.to,
type: config.site.ONLINE,//在线
message: data.msg
});
var message_friend = new Message({
uid: data.to, //朋友,data.to中保存的是朋友的fid
from: data.from,
to: data.to,
type: data.type,//朋友需要判断是否在线
message: data.msg
});
方式一,findOne
User.findOne({username: data.usr }, function(err, doc) {
......
}
})
方式2. find()+ exec(函数体)
, 其中exec
是execute
执行下一个函数的意思
User.find()
.exec(function(err, docs) {
......
})
方式3.
populate
方法用来查询两张表Friend.find({‘uid‘: uid}) //找到uid对应的uid
.populate(‘fid‘) //查找fid对应的user表
.exec(function(err, docs){
....
})
首先用户加入到一个唯一的sessionId的房间socket.emit(‘join‘, sessionId);
用户发送消息给socketsocket.send(_id,fid,msg);
socket给uid发送消息msgio.to(uid).emit(‘msg‘, uid,fid,msg);
socket给fid发送消息msgio.to(fid).emit(‘msg‘, uid,fid,msg);
服务器端监听消息
socket.on(‘message‘, function(uid,fid,msg){
var type;//在线还是不在线
if(onlineList.indexOf(fid) === -1){//判断朋友是不是在线
type= config.site.OFFLINE;//用户不在线
//socket给自己发送消息不在线
io.to(uid).emit(‘msg‘, uid,fid,msg);
}else {
type=config.site.ONLINE;//在线
io.to(fid).emit(‘msg‘, uid,fid,msg);//socket给朋友发送消息
io.to(uid).emit(‘msg‘, uid,fid,msg);//socket给自己发送消息
}
//构建一个data的json数据
var data = {
"uid": uid,
"from": uid,//自己
"to": fid,//朋友
"type": type,
"msg": msg
};
//调用dbHelper中的addMessage函数来将消息存放到数据库
dbHelper.addMessage(data, function(success,data){
...
});
});
socket.on(‘msg‘, function(uid, fid, msg) {
fromID = (_id == fid)?uid:fid; //接受到的消息的发送人id
if (_id == fid) {
fImg = $(‘#‘+uid).children(‘img‘).attr(‘src‘);//获取到图片路径
message = $.format(TO_MSG, fImg, msg)//格式化为发送的消息
} else {
message = $.format(FROM_MSG, _img, msg); //格式化为收到的消息
}
$("#v"+fromID).append(message); //将消息append添加到前端
$("#v"+fromID).scrollTop($("#v"+fromID)[0].scrollHeight);
});
如果用户与用户之间的聊天不是在同一个聊天室的话,那么他们的聊天消息会出错
所以我们要为用户指定一个唯一的聊天室id
roomId = (uid>fid)?(uid+fid):(fid+uid);
type
,表示朋友是否在线exports.getOfflineMsg = function (data, cb) {
var uid = data.uid;
Message.find({‘uid‘:uid, ‘type‘:‘1‘})
.populate(‘from‘)
.exec(function(err, docs) {
var messageList=new Array();
for(var i=0;i<docs.length;i++) {
messageList.push(docs[i].toObject());
}
cb(true, messageList);
});
}
将取出的消息渲染到前端的页面
var msg = $.format(TO_MSG, result[i].from.imgUrl, result[i].msg);
...
$("#v"+fid).append(msg);
var conditions = {‘uid‘:uid, ‘from‘:fid, ‘type‘:‘0‘};
var update = {$set :{ ‘type‘ : ‘1‘}};
var options = { multi: true };
var uid = data.uid;
var fid = data.fid;
var conditions = {‘uid‘:uid, ‘from‘:fid, ‘type‘:‘0‘};
var update = {$set :{ ‘type‘ : ‘1‘}};
var options = { multi: true };
Message.update(conditions,update,options, function(error,data){
if(error) {
console.log(error);
}else {
data.id = fid;
cb(true, data);
}
})
小礼物走一走,来简书关注我
标签:根据 ons code sel write orm pwd 本地 pytho
原文地址:https://www.cnblogs.com/williamjie/p/9448634.html