Writing empty object with socket.io - json

I'm currently trying to send some information via Socket.io with Node.js but it looks like I'm doing something wrong and I really don't know why.
I have some containers on my machine using Docker and I use the Docker.io node package for my app in order to get all the information I want.
Here's the server side function that sends the data
io.sockets.on('connection', function(socket){
socket.emit('message',container);
});
var container = docker.containers.list(handler);
function handler(err, res) {
if (err) throw err;
console.log("data returned from Docker as JS object: ", res);
}
Here's the client side code that gets the socket message
var socket = io.connect('/');
socket.on('message', function(data){
console.log(data);
});
The data that I'm sending through the socket ( the container list looks) like this:
[ { Command: 'top ',
Created: 1393878688,
Id: 'fa46297fa16ff184673077545437a64f2adaf62db8774be696d76cc9f52b7881',
Image: 'ubuntu:12.04',
Names: [ '/cranky_archimedes' ],
Ports: [],
Status: 'Up 20 minutes' } ]
But the only thing I get client side is : Object {}
and the socket.io log is sending me this:
debug - websocket writing 5:::{"name":"message","args":[{}]}
[ { Command: 'top ',
Created: 1393878688,
Id: 'fa46297fa16ff184673077545437a64f2adaf62db8774be696d76cc9f52b7881',
Image: 'ubuntu:12.04',
Names: [ '/cranky_archimedes' ],
Ports: [],
Status: 'Up 20 minutes' } ]
The args section is empty. I really don't know how I can put the container list JSON into that arg so it can be send proprely. Am I missing something?
EDIT 1:
When I log before emitting my container variable looks like this:
{ callback: [Function: handler] }

There are actually a few errors here. First container is not what you think it is. It is not the result of docker.containers.list(), it is a function.
Consider the following example
var hello = function(){
return "hello";
}
console.log(hello); // [Function]
console.log(hello()); // hello
hello is the function that returns "hello" but hello is not equal to "hello".
Basically when you are sending container, you aren't actually sending the result of docker.containers.list(), but the function itself.
Your second problem is that you are using an async function, but you are not waiting for the callback of this function to emit your data.
So basically with your current code, you are sending the wrong thing, at the wrong time.
What you need to do in order to make things work is probably something like this :
io.sockets.on( 'connection', function( socket ) {
docker.containers.list( function( err, res ) {
socket.emit( 'message', res );
});
});
Haven't tried it, but it should work!

your client code looks like this:
socket.on('message', function(data)){
//this console.log is not actually inside the callback
console.log(data);
}
It needs to look like this:
socket.on('message', function(data) {
//here the log is inside the callback
console.log(data);
});

Related

I can't fill a request response using axios in state variable in React.js with Next.js

I'm working with React.js and I have the following problem:
import axios from "axios";
export default function Home() {
const [products, setProducts] = useState([]);
const ax = axios.create({ headers: { Accept: 'application/json' }});
function test() {
const res = ax.get("https://vtexstore.codeby.com.br/api/catalog_system/pub/products/search").then((response) => {
// expected the setProducts to be filled with the return of this request
setProducts(response.data);
});
}
test();
// and when I get here to see if the products have been filled, I get an empty array [ ]
console.log(products);
/*
as the products variable was not filled within the axios promise by setProducts,
there is no way to throw the products array here in the HTML to make a forEach or
a map to look cute together with the tags
*/
return (
<sup>how sad, with the product array empty, I can't put the data here '-'</sup>
);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>
See how the result comes out in the IDE console:
I'm in Visual Studio not knowing what to do, I'm new to ReactJS with NextJS and from an early age I've been trying to see if I could solve this problem, but without success.
What can I do to bring the products to the HTML page?
UPDATE: As per the solution below, I created a possible workaround that indicates a path that could have returned a solution
ax.get("https://vtexstore.codeby.com.br/api/catalog_system/pub/products/search/", {})
.then((response) => setProducts(response.data))
.catch((error) => {
console.log(error); // AxiosError {message: 'Network Error', name: 'AxiosError', ...}
console.log(error.status); // undefined
console.log(error.code); // ERR_NETWORK
});
useEffect(() => {
console.log(products);
}, []);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.0.2/umd/react-dom.production.min.js"></script>
and I'm getting the same error that I put in the comments of the first answer below:
but when I change the setProducts by the console.log to see if it returns the same result, this appears in the terminal where my next.js application is running
that:
ax.get("https://vtexstore.codeby.com.br/api/catalog_system/pub/products/search/", {})
.then((response) => console.log(response.data.length)) // returns the length of the products array
returns this when I update my app:
NOTE: That's why I'm not able to understand my application in Next.js. I'm following all the correct guidelines, writing the code perfectly using axios and when I run the application on the website it gives a network error and doesn't show exactly the amount of products that were displayed in the terminal where my application is running.
I've already configured all the request headers correctly, enabling CORS to allow external requests with other API's, and I still don't succeed in returning the data to my application's page.
Wrap the stuff you have to fetch products inside useEffect hook
useEffect(()=>{
const ax = axios.create({ headers: { Accept: 'application/json' }});
function test() {
const res = ax.get("https://vtexstore.codeby.com.br/api/catalog_system/pub/products/search").then((response) => {
// expected the setProducts to be filled with the return of this request
setProducts(response.data);
console.log(response.data)
});
}
test();
},[])
Then in your return of the component, you can use map on products array with null and undefined checks
Like
{products && products.map(product=>{})}

FeathersJS - Making sure only the user that registers gets "users created"

I would like to make sure that only the socket which sends a registration / "users create" message gets the according "users created" response. There is a simple example for that in the documentation looking like this:
// Publish the `created` event to admins and the user that sent it
app.service('users').publish('created', (data, context) => {
return [
app.channel('admins'),
app.channel(app.channels).filter(connection =>
connection.user._id === context.params.user._id
)
];
});
However this is not working for me. If I log the context.params object, this simply looks like this when registering a new user:
{ query: {},
route: {},
connection: { provider: 'socketio' },
provider: 'socketio' }
Accordingly, the appropriate connection does not get the event. Am I missing something here? Do I have to add something in the registration process for this to work? Thanks a lot!
The easiest solution would be to not worry about dispatching the real-time event to that user at all. If the same connection is already calling .create the result from that promise (.create(data).then(userData => {})) will be the same as the dispatched event.
If you'd still like to have a newly created user join certain channels you can use params.connection in an after hook as shown in this issue:
app.service('users').hooks({
after: {
create(context) {
const { params: { connection }, result } = context;
if(connection) {
context.app.channel(`user/${result.id}`).join(connection);
}
return context;
}
}
});

firebase-queue - worker not lauching when defining specs

I m using firebase-queue and I want to use the specs functionnality. I did the following :
-server side :
var queueRef = firebase.database().ref('queue');
queueRef.child('specs').set({
register: {
start_state : 'register_user',
in_progress_state: 'register_user_in_progress',
timeout: 1000
}
});
var optionRegister = {
specId : 'register',
numWorkers: 1
};
//my worker
var registerQueue = new Queue(queueRef,optionRegister,function(data, progress, resolve, reject) {
// Read and process task data
console.log(data);
});
-client side :
var ref = firebase.database().ref('queue/tasks');
ref.push({ '_start': 'register_user', 'id': user1 });
In the firebase database, I see the task and the specs are correctly added :
my database view
-Versions
Node.js v7.0.0
firebase v3.5.3
firebase-queue v1.5.0
The problem is that the task is never taken by the worker and I cannot find why. Can anyone help me ? Thanks.
Everything seems correct except, '_start' object. It's actually '_state' object. Try changing this. Hope this will help.
ref.push({ '_state': 'register_user', 'id': user1 });

Backbone: fetching from URL in router gets undefined, but it works when collection gets JSON from a variable

From a JSON stored in a variable I can get the name of the current id from a router function called show: function(id). However, when I fetch collection from an URL instead of using a JSON variable I get an undefined TypeError.
console.log(this.collection.get(id).get('name'));
What I have seen is that when I use a JSON variable the show function works fine, but when I fetch from URL, show function executes after fetch succeed.
What I am doing wrong? Why fetching from URL gets undefined? How can I make it work?
The following code is fictional, it only shows the relevant part of my code. See the two cases at the end of the code block.
jsFiddle here
// Data 1 with variable
var heroes = [
{"id": "1", "name": "Batman"},
{"id": "2", "name": "Superman"},
];
// Data 2 from url: http://example.com/heroes.json
[
{"id": "1", "name": "Batman"},
{"id": "2", "name": "Superman"},
];
HeroesCollection = Backbone.Collection.extend({
model: HeroesModel,
url: 'http://example.com/heroes.json'
});
HeroesRouter = Backbone.Router.extend({
// I use two shows to graphic this example
routes: {
'': 'index',
':id': 'show'
},
initialize: function(options) {
this.collection = options.collection;
this.collection.fetch();
// this.collection.fetch({async:false}); this fixes my problem, but I heard it is a bad practice
},
index: function() {
},
show: function(id) {
console.log(this.collection.get(id).get('name'));
// Case #1: When Collection loads from a Variable
// id 1 returns: 'Batman'
// Case #2: When Collection fetchs from URL, id 1 returns:
// TypeError: this.collection.get(...) is undefined
}
});
// Case #1: collection loads JSON from a variable
var heroesCollection = new HeroesCollection(heroes);
// Case #2: collection loads JSON with fetch in router's initialize
// var heroesCollection = new HeroesCollection();
var heroesRouter = new HeroesRouter({collection: heroesCollection});
How about this? It's been awhile, but this seems like a better approach to what you are trying to achieve. The basic concept is that once you navigate to your show route, it will execute show. This method will create a new, empty collection, and then fetch the data for it. Along with that, we pass in a success method (as François illustrated) which will execute when the request is finished with the JSON (which creates a collection of Heros).
I believe the reason you were running into the issue with the remote data is that you were trying to access this.collection before it was populated with data from the request.
You have to remember the request is asynchronous, which mean code execution continues while the request is processing.
HeroesCollection = Backbone.Collection.extend({
model: HeroesModel,
url: 'http://example.com/heroes.json'
});
HeroesRouter = Backbone.Router.extend({
routes: {
'': 'index',
':id': 'show'
},
index: function() {
},
show: function(id) {
this.herosCollection = new HerosCollection();
this.herosCollection.fetch({
success: function(collection, response, options) {
console.log(this.get(id).get('name'));
}
});
}
});
you need to trigger the router 'show' function when the collection has ended to load.
this.collection.fetch({async:false}); fixes your problem because the whole javascript code is waiting (async:false) the ajax call to be ended before going further.
The other and best solution is to wait that your collection is fetched before you try to use the results.
Basically:
MyCollection.fetch({
success: function(model, reponse) {
// do wtv you want with the result here or trigger router show method...
}
});

IBM Worklight JSONStore - Add and get data

I am using worlight JSONstore. I am new to it. I tried searching that read all docs but didn't get much idea.
I have one login page from that I get some json data I want to store that data using jsonstore. and get that afterwards.
I made jsonstore adapter.
Json-Store-Impl.js
function getJsonStores(custData) {
var data = custData;
return data;
//custdata is json
}
function addJsonStore(param1) {
var input = {
method : 'put',
returnedContentType : 'json',
path : 'userInputRequired'
};
return WL.Server.invokeHttp(input);
}
function updateJsonStore(param1) {
var input = {
method : 'post',
returnedContentType : 'json',
path : 'userInputRequired'
};
return WL.Server.invokeHttp(input);
}
function deleteJsonStore(param1) {
var input = {
method : 'delete',
returnedContentType : 'json',
path : 'userInputRequired'
};
return WL.Server.invokeHttp(input);
}
after that I Create a local JSON store.
famlCollection.js
;(function () {
WL.JSONStore.init({
faml : {
searchFields: {"response.mci.txnid":"string","response.mci.scrnseqnbr":"string","response.loginUser":"string","request.fldWebServerId":"string","response.fldRsaImageHeight":"string","request.fldRequestId":"string","request.fldTxnId":"string","response.fldDeviceTokenFSO":"string","response.fldRsaCollectionRequired":"string","response.datlastsuccesslogin":"string","response.fldRsaUserPhrase":"string","response.fldRsaAuthTxnId":"string","response.rc.returncode":"string","response.datcurrentlogin":"string","response.mci.deviceid":"string","response.customername":"string","request.fldDeviceId":"string","response.fldRsaUserStatus":"string","request.fldScrnSeqNbr":"string","response.fldRsaImageWidth":"string","request.fldLangId":"string","response.fldTptCustomer":"string","response.encflag":"string","response.rc.errorcode":"string","response.fldRsaImagePath":"string","response.mci.appid":"string","response.mci.requestid":"string","response.rc.errormessage":"string","response.mci.appserverid":"string","response.fldRsaCollectionType":"string","request.fldAppId":"string","response.fldRsaImageId":"string","request.fldLoginUserId":"string","response.mci.sessionid":"string","response.mci.langid":"string","response.mci.remoteaddress":"string","request.fldAppServerId":"string","response.mci.webserverid":"string","response.fldRsaImageText":"string","response.fldRsaEnrollRequired":"string","response.fldRsaActivityFlag":"string"},
adapter : {
name: 'JsonStore',
replace: 'updateJsonStore',
remove: 'deleteJsonStore',
add: 'addJsonStore',
load: {
procedure: 'getJsonStores',
params: [],
key: 'faml'
},
accept: function (data) {
return (data.status === 200);
}
}
}
}, {
password : 'PleaseChangeThisPassword'
})
.then(function () {
WL.Logger.debug(['Take a look at the JSONStore documentation and getting started module for more details and code samples.',
'At this point there is no data inside your collection ("faml"), but JSONStore is ready to be used.',
'You can use WL.JSONStore.get("faml").load() to load data from the adapter.',
'These are some common JSONStore methods: load, add, replace, remove, count, push, find, findById, findAll.',
'Most operations are asynchronous, wait until the last operation finished before calling the next one.',
'JSONStore is currently supported for production only in Android and iOS environments.',
'Search Fields are not dynamic, call WL.JSONStore.destroy() and then initialize the collection with the new fields.'].join('\n'));
})
.fail(function (errObj) {
WL.Logger.ctx({pretty: true}).debug(errObj);
});
}());
When I clicked on login button I call getJsonStores like this -
getJsonStores = function(){
custData = responseData();
var invocationData = {
adapter : "JsonStore",
procedure : "getJsonStores",
parameters : [custData],
compressResponse : true
};
//WL.Logger.debug('invoke msg '+invocationData, '');
WL.Client.invokeProcedure(invocationData, {
onSuccess : sucess,
onFailure : AdapterFail,
timeout: timeout
});
};
I followed these steps
Is this right way? and how can I check jsonstore working locally or not? and how can I store my jsondata in JSONStore? Where should I initialize the wlCommonInit function in project?
plz Help me out.
Open main.js and find the wlCommonInit function, add the JSONStore init code.
WL.JSONStore.init(...)
You already have an adapter that returns the data you want to add to JSONStore, call it any time after init has finished.
WL.Client.invokeProcedure(...)
Inside the onSuccess callback, a function that gets executed when you successfully get data from the adapter, start using the JSONStore API. One high level way to write the code would be, if the collection is empty (the count API returns 0), then add all documents to the collection.
WL.JSONStore.get(collectionName).count()
.then(function (countResult) {
if(countResult === 0) {
//collection is empty, add data
WL.JSONStore.get(collectionName).add([{name: 'carlos'}, {name: 'mike'}])
.then(function () {
//data stored succesfully
});
}
});
Instead of adding [{name: 'carlos'}, {name: 'mike'}] you probably want to add the data returned from the adapter.
Later in your application, you can use the find API to get data back:
WL.JSONStore.get(collectionName).findAll()
.then(function (findResults) {
//...
});
There is also a find API that takes queries (e.g. {name: 'carlos'}), look at the getting started module here and the documentation here.
It's worth mentioning that the JSONStore API is asynchronous, you must wait for the callbacks in order to perform the next operation.