replicate pouchDB document with couchDB - javascript

I have used pouchDB in one application and now I want to introduce couchDB to sync the document to remote server. Hence i followed this link http://pouchdb.com/getting-started.html i used the below code to replicate the data to couchDB
var db2 = new PouchDB('todos');
var remoteCouch = 'http://localhost:5984/_utils/database.html?couchdb_sample';
db2.changes({
since: 'now',
live: true
}).on('change', showTodos);
sync();
function sync() {
//alert("sync");
//syncDom.setAttribute('data-sync-state', 'syncing');
//var opts = {live: true};
db2.replicate.to(remoteCouch).on('complete', function () {
console.log("done");
}).on('error', function (err) {
console.log(err);
});
function addTodo(text) {
var todo = {
_id: $("#eid").val()+$("#version").val(),
title: text,
name: $("#nameid").val(),
version: $("#version").val(),
completed: false
};
db2.put(todo, function callback(err, result) {
if (!err) {
console.log('Successfully posted a todo!');
}
else{
console.log(err);
}
});}
here the title has an xml string as value. But i am facing below error
SyntaxError: Unexpected token <
at Object.parse (native)
for this line db2.replicate.to(remoteCouch). I manually created a new document in couchDb database and entered the same data it gave no error but when i try replicating it shows syntax error. Can anyone please hint me where I have gone wrong

http://localhost:5984/_utils/database.html?couchdb_sample
Points to a HTML site (copied over from the browsers address bar, right?). Remove the middle part:
http://localhost:5984/couchdb_sample

It look like you have not defined the remote database in the way PouchDb is expecting. You should use the "new PouchDb" call. The second line of your code is:
var remoteCouch = 'http://localhost:5984/_utils/database.html?couchdb_sample';
but I think it should be like this:
var remoteCouch = new PouchDB('http://localhost:5984/couchdb_sample');
I am not clear from your code what the name of the remote database is, but it would not normally end in ".html" as Ingo Radatz pointed out, so I have assumed it is couchdb_sample above. There is more information about replication on the PouchDb site.

Related

NodeJS Undefined JSON object

just posting a question as I have seen some other similar questions on here but none with a method that seemingly works for me.
I'm new to NodeJS and playing around with requesting data from an API. For my test here im just trying to pull ticker prices based on the input of a prompt from the user.
This works fine, however the object
This is the code I am using to try and make this work:
prompt.start();
prompt.get(['coin'], function (err, result) {
request({url: `https://min-api.cryptocompare.com/data/price?fsym=${result.coin}&tsyms=BTC,USD`, json:true}, function(err, res, json) {
if (err) {
throw err;
}
console.log(json);
var json = JSON.stringify(json);
var string2 = JSON.parse(json);
console.log(string2.btc_price);
console.log(json);
});
console.log('Retrieving: ' + result.coin);
});
The API request works, however it returns JSON that looks like this with my 3 console logs:
{ set_attributes: { btc_price: 1, usd_price: 15839.35 } }
undefined
{"set_attributes":{"btc_price":1,"usd_price":15839.35}} -- (Stringify'd response)
I want to be able to extract the btc_price & usd_price as variables, ive tried a few different methods and can't figure out where exactly im going wrong. Any help would be greatly appreciated!
Cheers,
J
When you attempt to extract the btc_price attribute, it's actually nested so your second console should read console.log(string2.set_attributes.btc_price);
axios has more stars on Github, more followers on Github and more forks.
Features
Make XMLHttpRequests from the browser
Make http requests from node.js
Supports the Promise API
Intercept request and response
Transform request and response data
Cancel requests
Automatic transforms for JSON data
Client side support for protecting against XSRF
Using async / await
// Make a request for a user with a given ID
var preload = null;
async function getPrice(symbol) {
preload = await axios.get('https://min-api.cryptocompare.com/data/price?fsym=${symbol}&tsyms=BTC,USD')
.then(function (response) {
preload = response.data;
})
.catch(function (error) {
console.log(error);
});
return `preload.BTC = ${preload.BTC}; preload.BTC = ${preload.BTC}`;
};
getPrice('ETH');
// return preload.BTC = 0.04689; preload.USD = 742.85

bidirectional communication with python-shell and node.js

I'm trying to communicate between node.js and python-shell. I was able to recieve data from python-shell-object but when I try to send a message to the python-shell it crashes.
my app.js:
var PythonShell = require('python-shell');
var options = {
scriptPath: '/home/pi/python'
};
var pyshell = new PythonShell('test.py', options, {
mode: 'text'
});
pyshell.stdout.on('data', function(data) {
pyshell.send('go');
console.log(data);
});
pyshell.stdout.on('data2', function(data) {
pyshell.send('OK');
console.log(data);
});
pyshell.end(function(err) {
if (err) throw err;
console.log('End Script');
});
and my test.py:
import sys
print "data"
for line in sys.stdin:
print "data2"
I basically want to have communication in a chronolical way:
recieve "data" from python
send "go" to python
recieve "data2" from python
Another Question:
In the tutorial on https://github.com/extrabacon/python-shell it is written that you have to write pyshell.on() to wait for data while in the source-code the author writes pyshell.stdout.on(). Why is that?
Thanks!!!
(wrong indention in python corrected)
Your code exhibits some incorrect use of python-shell. Here below I have put together some notes. However, this is just what I primarily spot as mistakes so it will just rectify the use of the python-shell library but it might not necessarily remove all issues with your Python counterpart.
Incorrect use of stdout.on('data')
You appear to incorrectly utilize the event handler stdout.on. The handler takes "data" as argument denotes the event which happens when an output message is printed from Python script. This always be stdout.on('data') regardless what messages are printed.
This one is not valid:
pyshell.stdout.on('data2', function(data) { .... })
It should always be
pyshell.stdout.on('data', function(data) { .... })
When relay a message to Python, you should enclose the command with end
You should change from:
pyshell.send('OK');
To this:
pyshell.send('OK').end(function(err){
if (err) handleError(err);
else doWhatever();
})
Therefore, rectifying those two mistakes, you code should become:
pyshell.stdout.on('data', function(data) {
if (data == 'data')
pyshell.send('go').end(fucntion(err){
if (err) console.error(err);
// ...
});
else if (data == 'data2')
pyshell.send('OK').end(function(err){
if (err) console.error(err);
// ...
});
console.log(data);
});

Update properties of a model

I am trying to implement a feature where I can press on a button to delete some properties of my model.
My Model is:
Request:
status
shopper
I am using an event based structure:
This is the front end
a.requests-deny(href='#', data-id=request.id) Deny request
and this is my backend
var Request = require('../../models/Request');
var ShopperRequests = Backbone.View.extend({
el: '.shoppers-requests',
events: {
'click .requests-deny' : 'requestDeny'
},
requestDeny: function(e){
e.preventDefault();
var target = $(e.currentTarget);
var requestId = target.data('id');
console.log(requestId);
Request.findById(requestId, function(err, request) {
console.log(request);
if (err) {
return console.log('oh no! error', err);
} else {
request.status = 'pending';
request.shopper = '';
request.save(function(err) { // <-- save it back to the database
if (err) {
console.log('oh no! could not be saved in db', err);
} else {
console.log(request);
}
});
}
});
},
Looking at the console in the browser I see that first of all I can't use "require" because "it's not defined"
Uncaught ReferenceError: require is not defined(anonymous function) # shopper-f28ac0daf1d6a206b3172e4b9c670dd4.js:1
I was thinking of taking the requestId and just updating the values in the database but apparently this is not working.
Any idea if this could work or how else I could implement it?
You are not loading the RequireJs library in your backend. Thats why you are getting require is not defined.
If you are using Node, add it like this:
npm install requirejs
Or else, download it from here, and add it to your project with a script tag.

nodejs mongoose doesn't return to console after saving an entry

I use a small piece of code from console to test saving/retrieving entries in MongoDB database. It looks like this:
var mongoose = require('mongoose');
var models = require('../models');
mongoose.connect('localhost', 'users');
var john = new models.User({ name:'John' });
john.save(function (err, john) {
if (err) {
console.log(err)
}
else {
console.log(john.name);
}
});
After I run it, it shows the name when it saves the entry, then doesn't return me to console and doesn't show any more messages. How can I make it return me to console?
Your node.js program won't exit as long as a database connection is still open, so you need to close your connection pool after you're done with it like this:
var mongoose = require('mongoose');
var models = require('../models');
mongoose.connect('localhost', 'users');
var john = new models.User({ name:'John' });
john.save(function (err, john) {
if (err) {
console.log(err)
}
else {
console.log(john.name);
}
mongoose.disconnect();
});
It returns you to the console once the call to save() is finished, but that's before your callback gets called.
If the save operation took several minutes you could continue playing with the console in the meantime.
When the save operation finishes, your callback gets called and prints the john.name to the console. Printing to the console while in the REPL can be somewhat tricky because it gets written where you are typing.
So my guess is you think that everything is blocked because you don't see the prompt > but it is in fact there, it's just that console.log wrote on that line. If you try other commands, it should still work.

"Meteor code must always run within a Fiber" when calling Collection.insert on server

I have the following code in server/statusboard.js;
var require = __meteor_bootstrap__.require,
request = require("request")
function getServices(services) {
services = [];
request('http://some-server/vshell/index.php?type=services&mode=json', function (error, response, body) {
var resJSON = JSON.parse(body);
_.each(resJSON, function(data) {
var host = data["host_name"];
var service = data["service_description"];
var hardState = data["last_hard_state"];
var currState = data["current_state"];
services+={host: host, service: service, hardState: hardState, currState: currState};
Services.insert({host: host, service: service, hardState: hardState, currState: currState});
});
});
}
Meteor.startup(function () {
var services = [];
getServices(services);
console.log(services);
});
Basically, it's pulling some data from a JSON feed and trying to push it into a collection.
When I start up Meteor I get the following exception;
app/packages/livedata/livedata_server.js:781
throw exception;
^
Error: Meteor code must always run within a Fiber
at [object Object].withValue (app/packages/meteor/dynamics_nodejs.js:22:15)
at [object Object].apply (app/packages/livedata/livedata_server.js:767:45)
at [object Object].insert (app/packages/mongo-livedata/collection.js:199:21)
at app/server/statusboard.js:15:16
at Array.forEach (native)
at Function.<anonymous> (app/packages/underscore/underscore.js:76:11)
at Request._callback (app/server/statusboard.js:9:7)
at Request.callback (/usr/local/meteor/lib/node_modules/request/main.js:108:22)
at Request.<anonymous> (/usr/local/meteor/lib/node_modules/request/main.js:468:18)
at Request.emit (events.js:67:17)
Exited with code: 1
I'm not too sure what that error means. Does anyone have any ideas, or can suggest a different approach?
Just wrapping your function in a Fiber might not be enough and can lead to unexpected behavior.
The reason is, along with Fiber, Meteor requires a set of variables attached to a fiber. Meteor uses data attached to a fiber as a dynamic scope and the easiest way to use it with 3rd party api is to use Meteor.bindEnvironment.
T.post('someurl', Meteor.bindEnvironment(function (err, res) {
// do stuff
// can access Meteor.userId
// still have MongoDB write fence
}, function () { console.log('Failed to bind environment'); }));
Watch these videos on evented mind if you want to know more:
https://www.eventedmind.com/posts/meteor-dynamic-scoping-with-environment-variables
https://www.eventedmind.com/posts/meteor-what-is-meteor-bindenvironment
As mentioned above it is because your executing code within a callback.
Any code you're running on the server-side needs to be contained within a Fiber.
Try changing your getServices function to look like this:
function getServices(services) {
Fiber(function() {
services = [];
request('http://some-server/vshell/index.php?type=services&mode=json', function (error, response, body) {
var resJSON = JSON.parse(body);
_.each(resJSON, function(data) {
var host = data["host_name"];
var service = data["service_description"];
var hardState = data["last_hard_state"];
var currState = data["current_state"];
services+={host: host, service: service, hardState: hardState, currState: currState};
Services.insert({host: host, service: service, hardState: hardState, currState: currState});
});
});
}).run();
}
I just ran into a similar problem and this worked for me. What I have to say though is that I am very new to this and I do not know if this is how this should be done.
You probably could get away with only wrapping your insert statement in the Fiber, but I am not positive.
Based on my tests you have to wrap the insert in code I tested that is similar to the above example.
For example, I did this and it still failed with Fibers error.
function insertPost(args) {
if(args) {
Fiber(function() {
post_text = args.text.slice(0,140);
T.post('statuses/update', { status: post_text },
function(err, reply) {
if(reply){
// TODO remove console output
console.log('reply: ' + JSON.stringify(reply,0,4));
console.log('incoming twitter string: ' + reply.id_str);
// TODO insert record
var ts = Date.now();
id = Posts.insert({
post: post_text,
twitter_id_str: reply.id_str,
created: ts
});
}else {
console.log('error: ' + JSON.stringify(err,0,4));
// TODO maybe store locally even though it failed on twitter
// and run service in background to push them later?
}
}
);
}).run();
}
}
I did this and it ran fine with no errors.
function insertPost(args) {
if(args) {
post_text = args.text.slice(0,140);
T.post('statuses/update', { status: post_text },
function(err, reply) {
if(reply){
// TODO remove console output
console.log('reply: ' + JSON.stringify(reply,0,4));
console.log('incoming twitter string: ' + reply.id_str);
// TODO insert record
var ts = Date.now();
Fiber(function() {
id = Posts.insert({
post: post_text,
twitter_id_str: reply.id_str,
created: ts
});
}).run();
}else {
console.log('error: ' + JSON.stringify(err,0,4));
// TODO maybe store locally even though it failed on twitter
// and run service in background to push them later?
}
}
);
}
}
I thought this might help others encountering this issue. I have not yet tested calling the asynchy type of external service after internal code and wrapping that in a Fiber. That might be worth testing as well. In my case I needed to know the remote action happened before I do my local action.
Hope this contributes to this question thread.

Categories