Making async call dropboxjs - javascript

I have problem when I want to read directories from the Dropbox API, dropbox.js https://github.com/dropbox/dropbox-js
The read directories function from the the API looks something like this and I want to assign the value with angular to easily reach it in my HTML.
UPDATE AFTER HELPFUL QUESTION
client.readdir("/", function(error, entries, stat1, stat2) {
if (error) {
return showError(error);
}
$scope.dbItems = stat1;
$scope.$digest();
});
The HTML-code:
<ul ng-repeat="dbItem in dbItems">
<li><input type="image" src="img/folder.png">{{dbItem.name}}</input></li>
</ul>
My problem is that the Dropbox call takes some milliseconds so I have to reload the page to print the data collected. I've tried some things with both angular and JQuery promises but I can't get i to work. All the examples I find about promises has a setTimeout-function and that is fairly easy to implement but when I try to implement it with Dropbox it doesn't work. Anyone who has tried something similar?
UPDATE WITH MY PROBLEM
Now the HTML is updated correctly but I also want to join all of my Dropbox directories to be exported as JSON. I've updated the function above to look like:
$scope.listDB = function()
{
client.readdir(dirToString(), function(error, entries, stat1, stat2) {
if (error) {
return showError(error); // Something went wrong.
}
$scope.dbItems = stat2;
$scope.$digest();
testTemp = stat1._json;
setFolders(testTemp);
function setFolders(current)
{
for(var i=0,folders = current.contents;i<folders.length;i++)
{
if(folders[i].is_dir)
{
folders[i].name = folders[i].path.replace(/\/([^)]+)\//,"");
folders[i].name = folders[i].name.replace('/',"");
$scope.listDBinner(folders[i].name);
var inner = $scope.innerItems;
folders[i].contents = inner;
setFolders(folders[i]);
}
}
}
});
};
With listDBinner:
$scope.listDBinner = function(name)
{
client.readdir(name, function(error, entries, stat1, stat2) {
if (error) {
return showError(error); // Something went wrong.
}
$scope.innerItems = stat1;
$scope.$digest();
console.log($scope.innerItems);
});
console.log($scope.innerItems);
};
The problem is that the console.log of $scope.innerItems inside of client.readdir is correct and the one outside is just empty. I know this should probably be solved with Promises of some kind but I really can't get it to work.

Related

Dynamically get data from firebase realtime database during runtime in javascript

I have the following problem: I want to get data from a specific node from firebase during runtime. It should display "stats" of a player that was selected before. Now I could use on() to get all the data in the beginning, but I want to save data transfers by only downloading the data of on player if I need to, so I tried to use once like this:
var firebaseRef = firebase.database().ref();
function getScoresOfPlayer(player) {
console.log(player);
var selectedPlayerScores = [];
firebaseRef.once('value').then(function(snap) {
snap.child('scores').child('thierschi').forEach(function(child) {
selectedPlayerScores.push([child.key, child.val()]);
});
});
return selectedPlayerScores;
}
The problem is that it retruns the array before the data was loaded into it. Also I checked the docs and didn't find a better solution.
Thanks in advance!
This is because the getScoresOfPlayer function returns selectedPlayerScores before the promise returned by the once() method resolves.
You should include the return within the then(), as follows:
var firebaseRef = firebase.database().ref();
function getScoresOfPlayer(player) {
console.log(player);
var selectedPlayerScores = [];
return firebaseRef.once('value') //return here as well
.then(function(snap) {
snap.child('scores').child(player).forEach(function(child) { //I guess it should be child(player) and not child('thierschi') here
selectedPlayerScores.push([child.key, child.val()]);
});
return selectedPlayerScores;
});
}
which means that you have to call your function as follows, since it is going to be asynchronous and to return a promise:
getScoresOfPlayer('xyz')
.then(function(selectedPlayerScores) {
....
})

Promise in MagicSuggest data function

I have tried asking this question directly on github but there does not seem to be much movement in this project anymore. It would be great if someone on SO has an idea. Is it possible to return a promise in the data function? I have tried the following and it does not seem to work. The issue is that I am trying to make an ajax call within the data-function, which expects a result/data array. Of course I cannot do this when making an asynchronous ajax call.
var ms = $('#mycombo').magicSuggest({minChars: 2, data : function(q) {
return someAPI.findSuggestions(q, currentLang).then(function(response) {
if(!_.isEmpty(response.data.suggestions)) {
_.each(response.data.suggestions, function(suggestion) {
if (suggestion.id && suggestion.label) {
data.push({ id: suggestion.id, name: suggestion.label });
}
});
}
});
return data;
}});
If there is an alternative way of solving this, I would be very grateful for your help.
Thanks in advance.
Michael
For those interested, I have managed to find a solution to the problem. As posted on github (https://github.com/nicolasbize/magicsuggest/issues/281) you need to use the keyup event instead of setting the data property during initialization. So it now looks something like this:
var ms = $('#mycombo').magicSuggest({minChars: 2});
$(ms).on('keyup', function(e, m, v) {
// ... get data via ajax and call "ms.setData(data)" in the response callback ...
// ... you can use m.getRawValue() to get the current word being typed ...
ms.setData(data);
}
This will cause an ajax call to be fired after every key press, so you may want to improve this by adding some kind of a delay or something.
I've also done it this way:
const suggester: any = divElem.magicSuggest({
...more properties here...
data: (query) => {
if (query) {
this.myService.mySearch(query).take(1).subscribe((list) => {
suggester.setData(list);
});
}
return [];
},
...more properties here...
});
Where mySearch(query) returns:
Observable<MyObject[]>

Populate an array with meta data gathered from Xray

I've been trying to fill an array with metadata that I collect with Xray, and haven't had any success. The function is called by an API route on my server and gets the links from my application.
I seem to be struggling with promises as it takes time to scrape the metadata, and I can't seem to get the function to wait until the data has been collected before moving on. Perhaps, I'm just not understanding how Xray works? Or maybe promises? I've tried everything I can think of, this being the most recent attempt (and the simplest):
function createCollection() {
Promise.all(rawLinks.map(function(link) {
linksArray.push(xray(link, 'title')(function(error, title) {
console.log(title);
return title;
}))
}))
.then(linksArray => {
console.log(linksArray);
});
}
It's by far not the most robust or elaborate solution I've tried, but it's the most recent one. First the console logs an array with "undefined" as the data, THEN it logs the individual titles.
I would be very thankful for any help, or direction on what to research. Like I've said, I feel as if I've exhausted all my ideas and don't know where to even look anymore.
Figured it out, this seems to be doing the trick!
// format links into an array of objects
var rawLinks = links.split(', ');
var linksArray = [];
createCollection();
function createCollection() {
rawLinks.map(function(link) {
var fillMetaPromise = new Promise(
function(resolve, reject) {
var test = xray(link, 'title')(function(err, title) {
var data = { title: title, link: link };
resolve(data);
});
})
.then(data => {
processTitle(data.title, data.link);
});
});
}
function processTitle(title, link) {
var object = {
link: link,
title: title
};
linksArray.push(object);
console.log(linksArray);
}

Best practices for waiting on the result of a function in Meteor?

I've got this function that involves uploading an image to Cloudinary, and then setting the component's state to be the resulting URL. Here's what it looks like:
loadFileFront: function(e) {
var imageFrontURL = window.webkitURL.createObjectURL(e.target.files[0]);
var imageFrontFile = e.target.files[0];
var returnedURL = '';
Cloudinary._upload_file(imageFrontFile, {}, function(err, res) {
if (err){
console.log(err);
return;
}
console.log(res.url);
});
this.setState({
imageFront: returnedURL,
imageFrontFile: imageFrontFile
})
},
(Ignore that top line with createObjectURL).
I've been doing a bunch of research into how best to structure this so that setState waits on the the upload to complete the the res.url to be returned, thus updating the state properly. When I console.log res.url, after a few seconds it shows up. However when I try to set returnedURL to res.url, there's no waiting and it just jumps ahead through the rest of the function.
What's the best way to wait on the result of the Cloudinary upload here? I've been reading about the async / await support in Meteor 1.3, but I've been having trouble figuring out how to configure this Cloudinary upload method in a Meteor method on the server. Any help is appreciated!
If I understand the problem correctly, then this should fix it. You want to do a fat arrow function on the callback so you can correctly pass (this), and won't have any issues calling this.setState. Also since the key and value of imageFrontFile are the same, you can use it as I typed it below. Hope that helps.
loadFileFront: function(e) {
var imageFrontURL = window.webkitURL.createObjectURL(e.target.files[0]);
var imageFrontFile = e.target.files[0];
var returnedURL = '';
Cloudinary._upload_file(imageFrontFile, {}, (err, res) => {
if (err){
console.log(err);
return;
}
this.setState({
imageFront: res.url,
imageFrontFile
});
});
},
I think you can do the job with future. (https://www.npmjs.com/package/future)
Here's an example : https://www.discovermeteor.com/patterns/5828399

How to use getMapping function of Elasticsearch JS

I am trying to use this getMapping function seen here in the api. I am trying to get the mapping for an index in my database. So far I've tried this
var indexMap = client.indices.getMapping(['indexName'], function() {
console.log(indexMap);
});
and
var indexMap = client.indices.getMapping({index: 'indexName'}, function() {
console.log(indexMap);
});
both tries fail and log { abort: [Function: abortRequest] }
So I took a closer look at the ElasticSearch JS Quick Start docs to see how they were using the methods. I was confused by the API because I thought it was supposed to take an array client.indices.getMapping([params, [callback]]). But I now understand that it takes an object with params inside that object and then returns the response in a callback. The function does not return anything relevant as far as I can tell. Heres the code I used to get the mapping on 'myIndex' index. The mapping is stored in the response object.
Code:
client.indices.getMapping({index: 'patents'}, function(error, response) {
if (error) {
console.log(error);
} else {
console.log(response);
}
});

Categories