Im using django-channels to implement chat message box and connecting to websocket via ajax since the chat box doesn't take up a full screen . Im connecting to a particular socket when one user is selected and the messages are sending through the first time and its getting saved.When i close the chatbox im calling websocket close and disconnnect is executing,but when i close and reopen again im getting error
reconnecting-websocket.js:293 Uncaught INVALID_STATE_ERR : Pausing to
reconnect websocket
And also the messages can be seen in other channels as well when i open the chatbox.Is there any chance the websocket are remaining connected and channels aren't being discarded after disconnect is called?
My code:
class ChatConsumer(AsyncConsumer):
async def websocket_connect(self, event):
print("connected", event)
other_user = self.scope['url_route']['kwargs']['username']
me = self.scope['user']
thread_obj = await self.get_thread(me, other_user)
self.thread_obj = thread_obj
chat_room = "thread_{}".format(thread_obj.id)
self.chat_room = chat_room
await self.channel_layer.group_add(
chat_room,
self.channel_name
)
await self.send({
"type": "websocket.accept"
})
async def websocket_receive(self, event):
print("MEssage received",event)
front_text = event.get('text', None)
if front_text is not None:
loaded_dict_data = json.loads(front_text)
msg = loaded_dict_data.get('message')
me = self.scope['user']
myResponse ={
'message': msg,
'username': me.username
}
if msg is not "":
await self.create_chat_messages(me,msg)
await self.channel_layer.group_send(
self.chat_room,
{
"type": "chat_message",
"text": json.dumps(myResponse)
}
)
async def chat_message(self, event):
await self.send({
"type": "websocket.send",
"text": event['text']
})
async def websocket_disconnect(self):
await self.channel_layer.group_discard(
self.chat_room,
self.channel_name
)
print("disconnected")
#database_sync_to_async
def get_thread(self,user,other_username):
return Thread.objects.get_or_new(user,other_username)[0]
#database_sync_to_async
def create_chat_messages(self,me,msg):
thread_obj = self.thread_obj
if msg is not "":
print("MESSAGE",msg)
print(thread_obj)
print(me)
chat_message = ChatMessage.objects.create(thread=thread_obj, user=me, message=msg)
return chat_message
else:
return None
In my script i have:
$('.chatblob').click(function(e){
e.preventDefault();
$chatbox.removeClass('chatbox--empty');
var username = $(this).find('p:first').text();
console.log(username);
var loc = window.location;
var formData=$('#form');
var msgInput = $('#textmessage');
var wsStart = 'ws://';
if (loc.protocol == 'https:'){
wsStart ='wss://';
}
var endpoint = wsStart + loc.host+"/messages/"+username+"/";
console.log("endpoint: ",endpoint);
console.log("MESSAGE IS",msgInput.val());
$.ajax({
type: 'POST',
url:'/messages/'+username+"/",
data: {
'username': username,
'message': msgInput.val(),
csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val()
},
dataType: 'jsonp',
jsonpCallback: "localJsonpCallback"
});
$.ajax({
type: 'POST',
url:"/student/get-thread/"+username,
data: {
'username': String(username),
csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val()
},
dataType:'json',
success:function(e){
console.log(e);
console.log(e.success.queryset);
$('.chatbox__body').empty();
$('.chatbox__body').append(e.success.queryset);
},
error: function(e){
console.log(e)
}
});
function localJsonpCallback(json) {
if (!json.Error) {
console.log("success");
}
else {
console.log("Error");
}
}
var socket = new ReconnectingWebSocket(endpoint);
chatHolder= $('.chatbox__body');
var me = $('#myUsername').val();
sockets.push(socket);
socket.onmessage = function(e){
var chatDataMsg=JSON.parse(e.data);
console.log("chatmessage",chatDataMsg);
chatHolder.append(chatDataMsg.message);
}
socket.onclose = function(e){
console.log("CLosing",e);
}
socket.onopen = function(e){
console.log("open",e);
formData.submit(function(event){
event.preventDefault();
var msgText = msgInput.val()
var finalData = {
'message' :msgText
}
console.log(msgText);
socket.send(JSON.stringify(finalData));
console.log(JSON.stringify(finalData))
console.log(endpoint);
formData[0].reset();
});
}
socket.onerror = function(e){
console.log("error",e);
}
socket.onclose = function(e){
console.log("Closers",e);
}
});
});
It seems to have been a problem with using Reconnecting websocket since im using ajax. I changed to normal Websocket and now it is working fine.
Related
Chat is no displaying latest message sent or receive. When it come to some point it just stop scrolling for the new message.
This part is the sending.
function send(to_user, message){
let chat_box = $("#chat_box_" + to_user);
let chat_area = chat_box.find(".chat-area");
$.ajax({
url: base_url + "/send",
data: {to_user: to_user, message: message, _token: $("meta[name='csrf-token']").attr("content")},
method: "POST",
dataType: "json",
beforeSend: function () {
// console.log('adfasdf');
if(chat_area.find(".loader").length == 0) {
chat_area.append(loaderHtml());
}
},
success: function (response) {
},
complete: function () {
chat_area.find(".loader").remove();
chat_box.find(".btn-chat").prop("disabled", true);
chat_box.find(".chat_input").val("");
chat_area.animate({scrollTop: chat_area.offset().top + $(document).height()}, 800, 'swing');
}
});}
this for receiving
function displayMessage(message){
// let alert_sound = document.getElementById("chat-alert-sound");
if($("#current_user").val() == message.from_user_id) {
let messageLine = getMessageSenderHtml(message);
$("#chat_box_" + message.to_user_id).find(".chat-area").append(messageLine);
} else if($("#current_user").val() == message.to_user_id) {
// alert_sound.play();
// for the receiver user check if the chat box is already opened otherwise open it
cloneChatBox(message.from_user_id, message.fromUserName, function () {
let chatBox = $("#chat_box_" + message.from_user_id);
if(!chatBox.hasClass("chat-opened")) {
chatBox.addClass("chat-opened").slideDown("fast");
loadLatestMessages(chatBox, message.from_user_id);
chatBox.find(".chat-area").animate({scrollTop: chatBox.find(".chat-area").offset().top + $(document).height()}, 800, 'swing');
} else {
let messageLine = getMessageReceiverHtml(message);
// append the message for the receiver user
$("#chat_box_" + message.from_user_id).find(".chat-area").append(messageLine);
}
});
}}
Problem is when i send or receive message it dont display the latest message. It go back on a certain point.
I am trying to set the message to "Data Loading.." whenever the data is loading in the grid. It is working fine if I don't make an Ajax call. But, when I try to make Ajax Request, It is not showing up the message "Loading data..", when it is taking time to load the data. Can someone please try to help me with this.. Thanks in Advance.
_loadData: function(x){
var that = this;
if(this.project!=undefined) {
this.setLoading("Loading data..");
this.projectObjectID = this.project.value.split("/project/");
var that = this;
this._ajaxCall().then( function(content) {
console.log("assigned then:",content,this.pendingProjects, content.data);
that._createGrid(content);
})
}
},
_ajaxCall: function(){
var deferred = Ext.create('Deft.Deferred');
console.log("the project object ID is:",this.projectObjectID[1]);
var that = this;
console.log("User Reference:",that.userref,this.curLen);
var userObjID = that.userref.split("/user/");
Ext.Ajax.request({
url: 'https://rally1.rallydev.com/slm/webservice/v2.0/project/'+this.projectObjectID[1]+'/projectusers?fetch=true&start=1&pagesize=2000',
method: 'GET',
async: false,
headers:
{
'Content-Type': 'application/json'
},
success: function (response) {
console.log("entered the response:",response);
var jsonData = Ext.decode(response.responseText);
console.log("jsonData:",jsonData);
var blankdata = '';
var resultMessage = jsonData.QueryResult.Results;
console.log("entered the response:",resultMessage.length);
this.CurrentLength = resultMessage.length;
this.testCaseStore = Ext.create('Rally.data.custom.Store', {
data:resultMessage
});
this.pendingProjects = resultMessage.length
console.log("this testcase store:",resultMessage);
_.each(resultMessage, function (data) {
var objID = data.ObjectID;
var column1 = data.Permission;
console.log("this result message:",column1);
if(userObjID[1]==objID) {
console.log("obj id 1 is:",objID);
console.log("User Reference 2:",userObjID[1]);
if (data.Permission != 'Editor') {
deferred.resolve(this.testCaseStore);
}else{
this.testCaseStore = Ext.create('Rally.data.custom.Store', {
data:blankdata
});
deferred.resolve(this.testCaseStore);
}
}
},this)
},
failure: function (response) {
deferred.reject(response.status);
Ext.Msg.alert('Status', 'Request Failed.');
}
});
return deferred;
},
The main issue comes from your Ajax request which is using
async:false
This is blocking the javascript (unique) thread.
Consider removing it if possible. Note that there is no guarantee XMLHttpRequest synchronous requests will be supported in the future.
You'll also have to add in your success and failure callbacks:
that.setLoading(false);
I need send mails with nodemailer using ajax for show a message confirmation, with out reload my page.
other problem is if using the code ajax in the frontend send two mails
============================
app.js
app.post('/enviar', function(req,res){
var name = req.body.nombre;
var mail = req.body.correo;
var messege = req.body.mensaje;
var mail_from = "servicios#fractalservicios.com";
var subject_from = "Contact web fractal nodejs";
var transporter = nodemailer.createTransport(smtpTransport({
host: "*****",
port: ***,
auth: {
user: "****",
pass: "****"
}
}));
var mailOptions = {
from: name + ' ' + mail, // sender address
to: mail_from, // list of receivers
subject: subject_from , // Subject line
html: messege // html body
};
transporter.sendMail(mailOptions,function(error,result){
if(error){
console.log(error);
console.log("salio mal");
//res.end("error");
res.render('error',{titulo: 'error al enviar menmsaje'});
}else{
console.log("Message sent: " + res.message);
console.log("correcto");
res.redirect('/');
//res.render('enviado',{titulo: 'mensaje enviado'});
}
//res.redirect('/');
});
})
build.js => Front-end
var nombre = $('#nombre').val();
var correo = $('#correo').val();
var mensaje = $('#mensaje').val();
var enviar_info = {
"nombre": nombre,
"correo": correo,
"mensaje": mensaje
};
$('.send_mail').on('click',function(){
$.ajax({
type: "POST",
url: "/enviar",
data: JSON.stringify(enviar_info),
contentType:"application/json; charset=utf-8",
dataType: 'json',
success: function(e){
alert("genial se envio tu mensaje");
}
});
});
I recently ran into the same issue and I tried the following way. It worked like a magic for me, late answer but, I am sure someone else might need it...
$(function() {
$('#contact-form').on('submit', function(event) {
event.preventDefault();
let name = $('input[name="name"]').val(),
company = $('input[name="company"]').val(),
email = $('input[name="email"]').val(),
phone = $('input[name="phone"]').val(),
message = $('textarea[name="message"]').val();
$.ajax({
url: '/',
method: "POST",
contentType: 'application/json',
data: JSON.stringify({
name,
company,
email,
phone,
message
}),
success: function(response) {
console.log(response);
},
fail: function(error) {
console.log(error);
}
});
});
});
and in server.js
app.post('/', function(req, res) {
const output = `
<p>You have a new contact request</p>
<h3>contact details</h3>
<ul>
<li>Name: ${req.body.name}</li>
<li>Company: ${req.body.company}</li>
<li>Email: ${req.body.email}</li>
<li>Phone: ${req.body.phone}</li>
</ul>
<h3>Message</h3>
<p>${req.body.message}</p>
`;
let transporter = nodemailer.createTransport({
service: 'gmail',
host: 'mail.domain.com',
port: 465,
tls: {
rejectUnauthorized: false, //NOTE: you only need to set rejectUnauthorized to false if you are running on a local server, you can remove it after testing
}
});
let mailOptions = {
from: `nodemailer contact ${req.body.email}`,
to: 'info#domain.com',
subject: 'User Form Contact',
html: output
};
transporter.sendMail(mailOptions, function(error, info) {
if (error) {
return console.log(error);
}
console.log('Message sent: %s', info.messageId);
console.log('Preview URL: %s', nodemailer.getTestMessageUrl(info));
res.send({
msg: 'Email has been sent!'
});
});
});
Looking at the Flux Documentation I can't figure out how the code to a ajax update, and a ajax fetch would fit into the dispatcher, store, component architecture.
Can anyone provide a simple, dummy example, of how an entity of data would be fetched from the server AFTER page load, and how this entity would be pushed to the server at a later date. How would the "complete" or "error" status of request be translated and treated by the views/components? How would a store wait for the ajax request to wait? :-?
Is this what you are looking for?
http://facebook.github.io/react/tips/initial-ajax.html
you can also implement a fetch in the store in order to manage the information.
Here is an example (it is a concept, not actually working code):
'use strict';
var React = require('react');
var Constants = require('constants');
var merge = require('react/lib/merge'); //This must be replaced for assign
var EventEmitter = require('events').EventEmitter;
var Dispatcher = require('dispatcher');
var CHANGE_EVENT = "change";
var data = {};
var message = "";
function _fetch () {
message = "Fetching data";
$.ajax({
type: 'GET',
url: 'Url',
contentType: 'application/json',
success: function(data){
message = "";
MyStore.emitChange();
},
error: function(error){
message = error;
MyStore.emitChange();
}
});
};
function _post (myData) {
//Make post
$.ajax({
type: 'POST',
url: 'Url',
// post payload:
data: JSON.stringify(myData),
contentType: 'application/json',
success: function(data){
message = "";
MyStore.emitChange();
},
error: function(error){
message = "update failed";
MyStore.emitChange();
}
});
};
var MyStore = merge(EventEmitter.prototype, {
emitChange: function () {
this.emit(CHANGE_EVENT);
},
addChangeListener: function (callback) {
this.on(CHANGE_EVENT, callback);
},
removeChangeListener: function (callback) {
this.removeListener(CHANGE_EVENT, callback);
},
getData: function (){
if(!data){
_fetch();
}
return data;
},
getMessage: function (){
return message;
},
dispatcherIndex: Dispatcher.register( function(payload) {
var action = payload.action; // this is our action from handleViewAction
switch(action.actionType){
case Constants.UPDATE:
message = "updating...";
_post(payload.action.data);
break;
}
MyStore.emitChange();
return true;
})
});
module.exports = MyStore;
Then you need to subscribe your component to the store change events
var React = require('react');
var MyStore = require('my-store');
function getComments (){
return {
message: null,
data: MyStore.getData()
}
};
var AlbumComments = module.exports = React.createClass({
getInitialState: function() {
return getData();
},
componentWillMount: function(){
MyStore.addChangeListener(this._onChange);
},
componentWillUnmount: function(){
MyStore.removeChangeListener(this._onChange);
},
_onChange: function(){
var msg = MyStore.getMessage();
if (!message){
this.setState(getData());
} else {
this.setState({
message: msg,
data: null
});
}
},
render: function() {
console.log('render');
return (
<div>
{ this.state.message }
{this.state.data.map(function(item){
return <div>{ item }</div>
})}
</div>
);
}
});
I hope it is clear enough.
My node app posts an object (consisting of data collected in a form on the client) to Salesforce via their API. On receiving a success or error message, I would like to send it to the client-side, then display it. Socket.io seemed like the tool for this in my simple node/express3 app, but beyond the simple demo I'm not able to get data to pass between my server and my client.
My relevant server side code:
var express = require('express');
var port = 5432;
var app = module.exports = express();
var server = require('http').createServer(app);
var nforce = require('nforce');
var org = nforce.createConnection({
clientId: 'MY_CLIENT_ID',
clientSecret: 'MY_CLIENT_SECRET',
redirectUri: 'http://localhost:5432/oauth/_callback'
});
var io = require('socket.io').listen(server);
// here I authenticate with Salesforce, this works fine
app.post('/salesforce', function(req, res){
var lead = nforce.createSObject('Lead');
// here I construct the lead object, which also works fine
org.insert(lead, oauth, function(err, res) {
if (err === null) {
console.log(res);
leadSuccessMessage(res);
}
else {
console.log(err);
var error = {
errorCode: err.errorCode,
statusCode: err.statusCode,
messageBody: err.messageBody
};
console.log(error);
leadErrorMessage(error);
}
});
}
function leadSuccessMessage(res) {
var resp = res;
console.log('called success message from server');
io.sockets.on('connection', function (socket) {
socket.emit('sfRes', resp);
socket.on('thanks', function (data) {
console.log(data);
});
});
}
function leadErrorMessage(error) {
var err = error;
console.log('called error message from server');
io.sockets.on('connection', function (socket) {
console.log("socket is: " + socket);
socket.emit('sfRes', err);
socket.on('thanks', function (data) {
console.log(data);
});
});
}
And my relevant client side scripts:
<script src="/socket.io/socket.io.js"></script>
<script>
current.page = document.URL;
console.log("current page is: " + current.page);
var socket = io.connect(current.page);
socket.on('sfRes', function (data) {
console.log("client received: " + data);
fst.showLeadStatus(data);
socket.emit('thanks', {message: "received server feedback"});
});
</script>
When I post the form containing valid data using a spicy little AJAX call:
postToSF: function(){
$('#submitLead').on('click', function(e){
e.preventDefault();
var formData = $('#lead_form').serialize();
$.ajax({
type: 'POST',
url: '/salesforce',
data: formData,
success: function(){
fst.log('success!');
},
error: function(xhr, ajaxOptions, thrownError){
console.error(xhr.status); // 0
console.error(thrownError);
}
});
});
}
All I get are tears, and these in the server-side console:
// the result of `console.log(res)`
{ id: '00Qa000001FZfhKEAT', success: true, errors: [] }
// and proof that `leadSuccessMessage()` got called
called success message from server
Instead of calling this function from a client-side object as it's supposed to:
showLeadStatus: function(response){
if (response.success) {
fst.log("showing lead status as: " + response);
$('#leadStatus').addClass('success').removeClass('error').fadeIn().delay(4000).fadeOut();
}
else {
fst.log("showing lead status as: " + response);
$('#leadStatus').text(response.messageBody).addClass('error').removeClass('success').fadeIn().delay('4000').fadeOut();
}
$('#startOver').click();
}
Which works fine if I call it in the console passing it the data the server is supposed to be socketing over:
// this works, gosh darn it
fst.showLeadStatus({ id: '00Qa000001FZfhKEAT', success: true, errors: [] });
The Salesforce post error case doesn't surface anything to the client either. And there are no errors in the client or server console to contend with.
I'm stumped. Please help!
I would do something like this -
var mysocket = null;
var io = require('socket.io').listen(server);
io.sockets.on('connection', function (socket) {
mysocket = socket;
socket.on('thanks', function (data) {
console.log(data);
});
});
app.post('/salesforce', function(req, res){
....
....
})
function leadSuccessMessage(res) {
var resp = res;
console.log('called success message from server');
if(mysocket)
mysocket.emit('sfRes', resp);
}
function leadErrorMessage(error) {
var err = error;
console.log('called error message from server');
if(mysocket)
mysocket.emit('sfRes', err);
}