talking to PouchDB Basics - javascript

maybe it's an absolutely stupid question, but I have a Pouchdb Database that looks like this:
var fragDB = {
_id: new Date().toISOString(),
question: quest,
right: right,
wrong1: wrong1,
wrong2: wrong2,
wrong3: wrong3,
source1: source1,
source2: source2,
tags: tagarr
}
db.put(fragDB);
Now I want to retrieve the tags from the last document as an Array. I tried something like this, but this obviously didn't work.
var alltags = function(){
db.allDocs({include_docs: true, limit: 1, descending: true}, function(err, response){
if (err) {
console.log(err);
console.log("loading Standard Tags");
return ["..."];
}
if (response){
console.log(response.tags);
return response.tags;
}
});
};
What am I missing?

Not a dumb question – it just hard to grok, because PouchDB is asynchronous: http://pouchdb.com/guides/async-code.html
In your code, you have a function within a function, and it's the sub-function that's returning response.tags, not the parent function.
I suggest you read up on the link above, so you can learn how to write promisey async code like e.g.:
db.allDocs({
include_docs: true,
limit: 1,
descending: true
}).then(function (response) {
console.log(response.tags);
return response.tags;
}).catch(function (err) {
console.log(err);
console.log("loading Standard Tags");
return ["..."];
}).then(function (tags) {
// do something with the tags
});

Related

catch separated fails using deferred object

I got this code (using jquery)
function getData(applyFunction, callback) {
$.when(
$.getJSON("http://www.mocky.io/v2/59d72b5b120000c902cb1b4f"),
$.getJSON("http://www.mocky.io/v2/59d72b5b120000c902cb1b4f"),
).done(function(
firstData,
secondData
){
callback(applyFunction, {
firstDataToApply: { data: firstData.popup },
secondDataToApply: { data: secondData.popup }
})
})
}
Is there a way to catch separate errors from the $.getJSON part(or the when part), log those errors, and still be able to send both firstData and secondData(at the same time) to the callback function?
(I'm aware that if some or both $.getJSON fail I'd be sending empty data to the callback, and would have to null check before getting popup)
sorry for the confusing post, thanks in advance
Yes. Promises are pipelines and each handler in the pipeline can transform the value or error passing through, so you can turn a failure into a "success with null" if that's really want you want to do by adding a catch handler and returning null (or whatever value you want to transform the error into) from it. See the catch calls below and also the comments:
function getData(applyFunction, callback) {
$.when(
$.getJSON("http://www.mocky.io/v2/59d72b5b120000c902cb1b4f")
.catch(function(err) {
console.error(err);
return null;
}),
$.getJSON("http://www.mocky.io/v2/59d72b5b120000c902cb1b4f")
.catch(function(err) {
console.error(err);
return null;
})
).done(function(firstData, secondData) {
callback(applyFunction, {
firstDataToApply: {
data: firstData.popup // You'll need checks on this!
},
secondDataToApply: {
data: secondData.popup // And this!
}
});
});
}
Of course, if you're going to do this more than once or twice, you can avoid repeating yourself with a function:
function getJSONOrNull(url) {
return $.getJSON(url).catch(function(err) {
console.error(err);
return null;
});
}
then
function getData(applyFunction, callback) {
$.when(
getJSONOrNull("http://www.mocky.io/v2/59d72b5b120000c902cb1b4f"),
getJSONOrNull("http://www.mocky.io/v2/59d72b5b120000c902cb1b4f")
).done(function(firstData, secondData) {
callback(applyFunction, {
firstDataToApply: {
data: firstData.popup // You'll need checks on this!
},
secondDataToApply: {
data: secondData.popup // And this!
}
});
});
}

Mongodb, how to multiple request to aliment 1 object

i'm creating a forum, and i want to get the number of message in one topic,
so in my method GetListTopic i get the list of topic, and after i want to know how many message there is in one topic so i request the table forum_message for every topic in my list=>
db.Forum_Topic.count({}, function (err, topicount) { //nombre de topic
db.Forum_Topic.find().skip(skipNumber).limit(nombreDeTopicParPage).sort({ dateLastMessage: -1 }, function (err, dbres) {
//dbres = liste de topic
for (var i in dbres)
{
db.Forum_Message.count({ idTopic: new mongojs.ObjectID(dbres[i]._id) }, function (err, Messagecount) {
dbres[i].TotalMessage = Messagecount;
});
}
res.send([dbres, topicount]);
});
});
my need is to add in every object of my list the total message => dbres[i].TotalMessage = Messagecount;
but that don't work dbres[i].TotalMessage is set correctly in the function callback but when i send object TotalMessage doesn't exist ....
someone can help me please ?
The problem is that you are using for loop within an async function. And that res.send() statement does not wait for the loop to complete. It executes before.
There is a solution by using this async library. There are also many options in this library, however, I think the async.each() is the one you can try.
Good luck.
i finally found the solution to foreach update with nodejs and mongodb,
i use async.js here : https://www.npmjs.com/package/async
and to delete a liste of mail
async.each(ListeIdMailToDelete, function (mailID, callback) {
db.userMessageMail.find({ _id: db.ObjectId(mailID) }, function (err, dbres) {
if (dbres.length > 0)
{
if (dbres[0].expediteur == newplayer.pseudo || dbres[0].destinataire == newplayer.pseudo) {
db.userMessageMail.remove({ _id: dbres[0]._id }, function () {
callback(err);
})
}
}
});
}, function (err) {
console.log(err);
});

Meteor fetch on client undefined outside of helper

I am trying to fetch an entry in a collection with:
client/views/home.js:
criticalCrewNumber = ConfigValues.find({
name: 'criticalCrewNumber'
}).fetch()[0].value;
But I'm getting error:
Uncaught TypeError: Cannot read property 'value' of undefined
If I run the code in the browser console, the desired value is returned as a string.
I have tried various things, e.g. using findOne; placing the code elsewhere in the app; using iron-router waitOn for the subscription to come, etc. Every attempt so far has failed as I end up with undefined.
Here's how the collection is defined, published and subscribed to:
lib/config/admin_config.js:
ConfigValues = new Mongo.Collection("configValues");
ConfigValues.attachSchema(new SimpleSchema({
name: {
type: String,
label: "Name",
max: 200
},
value: {
type: String,
label: "Value",
max: 200
}
}));
both/collections/eventsCollection.js:
if (Meteor.isClient) {
Meteor.subscribe('events');
Meteor.subscribe('config');
};
server/lib/collections.js
```
Meteor.publish('events', function () {
return Events.find();
});
Meteor.publish('config', function () {
return ConfigValues.find();
});
```
Does anyone know what's going on? Thanks.
Consider using ReactiveVar (and Meteor.subscribe callbacks):
criticalCrewNumber = new ReactiveVar();
Meteor.subscribe('config', {
onReady: function () {
var config = ConfigValues.findOne({name: 'criticalCrewNumber'});
if (config) {
criticalCrewNumber.set(config.value);
} else {
console.error('No config value.');
}
},
onStop: function (error) {
if (error) {
console.error(error);
}
}
});

How to make multiple http requests in my case

I'm trying to chain a promise with Angular $resource.
I have the following factory:
angular.module('myApp').factory('Product', ['$resource', function ($resource) {
return $resource(
'/api/product/:name',
{ name: '#name' },
{ 'getSub': {
url: '/api/product/getSub/:name',
method: 'GET'}
}
);
}]);
I make multiple queries using my Product factory as such:
Product.query({'name': name}, function(product) {
Product.getSub({'name': product.name}, function(subItem) {
Product.getSub({'name':subItem.name}, function(childItem) {
//do stuff with child item
})
})
})
Is there a better way to do this? I feel like nesting all these calls is not a best practice.
You can chain the promises together!
Product.query({'name': name}).$promise
.then(function(product){
return Product.getSub({'name': product.name}).$promise;
})
.then(function(subItem){
return Product.getSub({'name': subItem.name}).$promise;
})
.then(function(item){
// etc
})
you can use waterfall of async library or implement it yourself.
here's sample code for your case.
async.waterfall([
function(callback) {
Product.query({'name': name}, function(product) {
callback(null, product);
})
},
function(product, callback) {
Product.getSub({'name': product.name}, function(subItem) {
callback(null, product, subItem);
})
},
function(product, subItem, callback) {
Product.getSub({'name':subItem.name}, function(childItem) {
var result = {};
result.childItem = childItem;
result.subItem = subItem;
result.product = product;
callback(null, result);
})
}
], function (err, result) {
//do stuff with result
});
If you want the requests to be done one after another (like you have in your example) you could do a recursive function like this:
in this example i want to upload a couple of images (calling a http route):
$scope.uploadImageLayout = function (currentIndex, numberOfItems) {
if (currentIndex === numberOfItems) {
// in here you could do some last code after everything is done
} else {
Upload.upload({
url: 'localhost:3000/ficheiros',
file: $scope.imagesToUpload[$scope.auxIndex].file
}).success(function (data, status, headers, config) {
if ($scope.auxIndex < numberOfItems) {
$scope.uploadImageLayout(currentIndex + 1, numberOfItems);
}
});
}
};
and the first time you call just do this:
$scope.uploadImageLayout(0, $scope.imagesToUpload.length);
in you case its the same but instead of the Upload.upload request you should have your request and catch the callback function(s).
A useful solution maybe use $q library
https://docs.angularjs.org/api/ng/service/$q
You can use the method $q.all() to send a lot of request and manage only one callback then() or make $q.defer() and resolve por reject your oun promises.
I currently answer this question from a mobile device and i can't make an example. Sorry about that.
If when I get home that mistake trains still try to help

How to populate jQuery UI Select2 with Restangular

I can't see why Restangular would behave differently inside a jquery-ui callback to the way it does anywhere else. Can you?
The following works in my controller:
Restangular.all('skills').getList().then(function(result) {
console.log(result);
});
However, when I use Restangular inside the query function for a jquery-ui-select2 (via angular-select2), it never makes a request.
HTML:
<input type="text" ui-select2="skillOptions" ng-model="skills">
JavaScript:
$scope.skillOptions = {
multiple: true,
query: function(query) {
// I see this:
console.log("Q:", query.term);
// this silently fails:
Restangular.all('skills').getList({
query: query.term
}).then(function(body) {
// this callback is never reached (nor is the error one)
var skills = body.skills;
console.log("got skills", skills);
query.callback({
data: {
text: 'name',
results: skills
}
});
}, function(error) {
console.error("Error getting skills", error);
});
}
};
Is there another way to use the query callback with Restangular or can anybody see why on Earth this wouldn't work?
The solution was to nest the callback in a $scope.$apply (since I am on AngularJS version 1.1.5) as per this bit of the documentation
Here's some working code:
$scope.skillOptions = {
multiple: true,
query: function(query) {
$scope.$apply(function() {
Restangular.all('skills').getList({
query: query.term
}).then(function(body) {
var skills;
skills = body.skills;
console.log("got skills", skills);
return query.callback({
results: _(skills).map(function(s) {
return {
text: s.name,
id: s.id
};
})
});
}, function(error) {
console.log("Error getting skills", error);
});
});
}
};

Categories

Resources