I have socket.emit call from client to server in response i want to have filename to the client that is not happening with below code not sure what is implemented wrong any idea, I do not see any error. How can i get response fro server using socket.emit ?
client.js
socket.emit('startRecording',function (response) {
console.log('start recording emit response',response);
});
server.js
socket.on('startRecording',function () {
var response;
logsRecording(function (filename) {
response = filename;
return response;
//socket.emit('filename',filename);
});
To acknowledge the message, your handler for the startRecording event needs to accept an acknowledgement callback as a parameter. You can then call that with your desired data. See Sending and getting data (acknowledgements)
socket.on('startRecording',function (socket, ackFn) {
var response;
logsRecording(function (filename) {
ackFn(filename);
});
});
Alternatively, you could add a listener for that filename event you have commented out, in the client.js:
socket.emit('startRecording');
socket.on('filename', function(filename) {
console.log('Filename received: ' + filename);
});
It might be helpful to run through Get Started: Chat application starting at the heading "Integrating Socket.IO" to get a more general understanding of Websockets.
Your server code should look like this:
socket.on('startRecording',function (callbackFn) {
var response;
logsRecording(function (filename) {
callbackFn(filename);
});
If you want to pass in data from your client:
socket.emit('startRecording', {someData: 'value'}, function (response) {
then server will be :
socket.on('startRecording',function (dataFromClient, callbackFn) {
Thank you for this helpfull hint
Here an 2020 "call" example call possible to use with moleculer microservices with four arguments:
The server responds in the callback function with two arguments err and res for the angular promise.
Angular 9 socket io
protected call(method: string, param?: any) {
try {
return new Promise((resolve, reject) => {
this.socket.emit("call", method, param, (err: any, res: unknown) => {
console.log(res);
if (err) { return reject(err); }
return resolve(res);
});
});
} catch (err) {
console.error(err);
}
}
Socket IO server response
socket.on('call', function(method, param, callbackFn){ // call method, param,
console.log(param);
switch (method) {
case "test":
console.log("test detected");
callbackFn(null , {name:"test",email:"test"});
break;
}
});
Related
I am currently writing a route which allows me to recieve information from a stored procudre I have in a database. I have written a request in AngularJS and a route in NodeJS but I am just recieving a pending request in the chrome Network developer window. I can see that the console.log in the NodeJs app has the data I require so it has retrieved it but there is nothing coming back in any of the console logs in the the AngularJS app.
Here is the code for the both the angularJS app and the Node App:
AnglaurJS:
checkForReplenishmentEmptyTrolley = async () => {
LIBRIS.extensions.openLoadingModal();
console.log('in checkForReplenishmentEmptyTrolley');
try {
const varPromise = await $http.get(`${LIBRIS.config.stockService}stockMovement/checkForUnattachedTrolley`)
.then((response) => {
console.log(response);
// Request completed successfully
}, (error) => {
// Request error
console.log(error);
});
console.log(varPromise.data);
// 1. check that there are no ghost replenish - lines 1-15
console.log('in try/catch');
console.log('promise', varPromise);
} catch (error) {
console.log(error);
}
},
NodeJS code:
app.get(`${ROUTE}/attachTrolley`, async function(req, res){
const newRequest = await DB.newRequest();
console.log('we have made it to the route');
try {
console.log('we have made it to the Try/Catch route');
newRequest.input();
const record = await newRequest.execute('dbo.usp_STK_CheckForUnattachedTrolley');
res.json(record)
console.log(record, 'record');
} catch (err){
handleError(res, err);
console.log(err);
}
});
The problem is that you are doing a .then on a awaited promises and not returning anything from that. You have two choice here
Either return response from then so when you try to access the value here console.log(varPromise.data); it works.
Or remove the .then alltogather as it is not required because you are awaiting it any ways.
Basically just do this
checkForReplenishmentEmptyTrolley = async () => {
LIBRIS.extensions.openLoadingModal();
console.log("in checkForReplenishmentEmptyTrolley");
try {
const varPromise = await $http.get(`${LIBRIS.config.stockService}stockMovement/checkForUnattachedTrolley`);
console.log(varPromise.data);
// 1. check that there are no ghost replenish - lines 1-15
console.log("in try/catch");
console.log("promise", varPromise);
} catch (error) {
console.log(error);
}
};
Hope this fixes your issue.
Solved it! I had no return statement in my route!
I have a little problem with acknowledgements function in socket io using nestjs framework.
Normally, with the code below, the data parameter in the onStartSearch function should contain the data and ack function to notify the frontend with. But the data params contain only data sent from the frontend.
Backend
#SubscribeMessage('startSearch')
async onStartSearch(socket, data) {
logger.info('User ' + socket.id + ' startedSearch');
logger.debug(data);
if (Joi.validate(data, requestSchema).error) {
return ack({
status: 'error',
reason: 'invalid params format',
});
}
Frontend
public sendMessage(payload: IChatMessage) {
this.socket.emit('message', payload, function(test) {
console.log("acckk received")
});
}
If you just return plain data, the acknowledgment (callback) function will automatically be called by nest:
#SubscribeMessage('startSearch')
async onStartSearch(socket, data) {
if (Joi.validate(data, requestSchema).error) {
return {
status: 'error',
reason: 'invalid params format',
};
}
}
But you can also work without the callback function (e.g. when working with native sockets which don't support the callback function):
The #SubsribeMessage methods can also return an Observable<WsResponse<any>>. WsResponse contains the event name and the payload {event: string, data: any}.
#SubscribeMessage('startSearch')
async onStartSearch(socket, data): Observable<WsResponse<any>> {
if (Joi.validate(data, requestSchema).error)
return of({event: 'searchResponse', data});
}
Then just listen to the response on your client:
socket.on('searchResponse', function (data) {
console.log('event', data);
});
I am trying to call a rest API from Firebase function which servers as a fulfillment for Actions on Google.
I tried the following approach:
const { dialogflow } = require('actions-on-google');
const functions = require('firebase-functions');
const http = require('https');
const host = 'wwws.example.com';
const app = dialogflow({debug: true});
app.intent('my_intent_1', (conv, {param1}) => {
// Call the rate API
callApi(param1).then((output) => {
console.log(output);
conv.close(`I found ${output.length} items!`);
}).catch(() => {
conv.close('Error occurred while trying to get vehicles. Please try again later.');
});
});
function callApi (param1) {
return new Promise((resolve, reject) => {
// Create the path for the HTTP request to get the vehicle
let path = '/api/' + encodeURIComponent(param1);
console.log('API Request: ' + host + path);
// Make the HTTP request to get the vehicle
http.get({host: host, path: path}, (res) => {
let body = ''; // var to store the response chunks
res.on('data', (d) => { body += d; }); // store each response chunk
res.on('end', () => {
// After all the data has been received parse the JSON for desired data
let response = JSON.parse(body);
let output = {};
//copy required response attributes to output here
console.log(response.length.toString());
resolve(output);
});
res.on('error', (error) => {
console.log(`Error calling the API: ${error}`)
reject();
});
}); //http.get
}); //promise
}
exports.myFunction = functions.https.onRequest(app);
This is almost working. API is called and I get the data back. The problem is that without async/await, the function does not wait for the "callApi" to complete, and I get an error from Actions on Google that there was no response. After the error, I can see the console.log outputs in the Firebase log, so everything is working, it is just out of sync.
I tried using async/await but got an error which I think is because Firebase uses old version of node.js which does not support async.
How can I get around this?
Your function callApi returns a promise, but you don't return a promise in your intent handler. You should make sure you add the return so that the handler knows to wait for the response.
app.intent('my_intent_1', (conv, {param1}) => {
// Call the rate API
return callApi(param1).then((output) => {
console.log(output);
conv.close(`I found ${output.length} items!`);
}).catch(() => {
conv.close('Error occurred while trying to get vehicles. Please try again later.');
});
});
I have an internally maintained npm package myNpmPackage which exports a function (for e.g. fnTestMicroSerConn ) as below:
const rp = require('request-promise-native')
exports.fnTestMicroSerConn = function () {
return new Promise(function(resolve, reject) {
var options = {
method: 'GET',
uri : "http://example.net",
resolveWithFullResponse: true,
}
rp(options)
.then(function (response) {
if (response.statusCode !== 200){
console.error("http not 200 but : ",response.statusCode)
resolve(false)
} else {
console.info("connected successfully : "+response.body)
resolve(response)
}
})
.catch(function (err) {
console.error("Error in establishing connectivity : ",err)
resolve(false)
})
})
}
I then need to call the above exported function from a Meteor method like so:
import { Meteor } from 'meteor/meteor';
import myNpmPackage from 'myNpmPackage';
Meteor.methods({
foo: function () {
myNpmPackage.fnTestMicroSerConn().then(function (response){
console.log(" My response: ",response.body);
return(response.body)
})
}
});
console.log(" My response: ",response.body); gets executed successfully and I can see the expected value in the server console log. So till here it's good.
However, now I want to pass the value of response.body to the client side. In short, when I do below on the client :
Meteor.call("foo", function (err, response) {
console.log("calling foo");
if(!err){
console.log("response : ",response);
} else {
console.log("err : ",err);
}
})
Unfortunately, currently I am getting undefined on the client for console.log("response : ",response);
Note: I am using the Meteor Promise package from here
Let me know if any more details are needed or any thing is unclear. I am very new to the Promise style of coding, hence, this can sound as a noob question.
Meteor methods called from clients by Meteor.call run synchronously to prevent clients from pending, even if a callback is supplied.
Your foo method does not wait for that promise inside. It runs past fnTestMicroSerConn() call without hesitation and ends up with no more statement to execute, returning undefined as a result. By the time the promise resolved and logged the expected message on the server console, the method had been exited.
To get resolved/rejected result of that promise, you can return the promise from the method to the caller, and the client would be able to respond to the promise.
Meteor.methods({
foo: function () {
return myNpmPackage.fnTestMicroSerConn();
}
});
Meteor.call("foo")
.then( response => console.log("My response: ", response.body) )
.catch( err => console.log("err : ",err) );
Meteor methods is powerful. The API documentation of methods contains much information and is worth mastery.
I'm trying to create a basic app in node.js that a) tracks a keyword in twitter and temporarily stores messages relating to that keyword, b) after enough messages have been accumulated, return it to the user. I'm using the ntwitter library.
I've a basic long polling system implemented on my client and server side, but I'm having some trouble on verification. The way I set it up currently, it verifies the user each time /api/streamfeed is called, so potentially every 30sec (since I have a 30s timeout schedule) before checking the stream. I'm thinking this will get me into trouble since I believe verification is rate-limited? Is there a way to check whether I'm verified without having to ping Twitter's API (perhaps store a boolean after the first attempt)?
Client side:
//upon receiving a response, poll again
function getStreamFeed() {
console.log('calling getStreamFeed');
$http.get('/api/streamfeed').success(function(data) {
console.log(data)
getStreamFeed();
});
};
setTimeout(getStreamFeed, 1000);
Server side:
app.get('/api/streamfeed', function(req, res) {
/*
...
polling code
...
*/
twit.verifyCredentials(function(err, data) {
if (err) res.send(404);
twit.stream('statuses/filter', {
track: 'justin bieber'
}, function(stream) {
stream.on('data', function(data) {
console.log(data.text)
messages.push(data.text);
});
})
});
});
I'd send the credentials back and resend them again... this could be a bool, or actual credentials to use. these aren't your private keys or anything, only the user's.
could also be sent in headers and cookies and properly hashed etc.
this just simply shows a pattern that should work.
client side:
function getStreamFeed(credentials) {
//upon receiving a response, poll again
console.log('calling getStreamFeed');
var url = '/api/streamfeed';
if (credentials) {
url += '&credentials=' + credentials;
}
$http
.get(url)
.success(function(data) {
console.log(data)
getStreamFeed(true);
});
};
setTimeout(getStreamFeed, 1000);
Server side:
app.get('/api/streamfeed', function(req, res) {
function twitStream () {
twit.stream('statuses/filter', {track: 'justin bieber'}, function(stream) {
stream.on('data', function(data) {
console.log(data.text)
messages.push(data.text);
});
}
}
var credentials = req.query.credentials;
if (credentials) {
twitStream()
}
twit.verifyCredentials(function(err, data) {
if (err) res.send(404);
twitStream()
});
});