Leaflet mapping: Assign object to fetch promise for local GeoJSON file - async-await

I am looking to assign as an object a Fetch API promise from a local GeoJSON file.
Here is the code
fetch("data/sites.geojson")
.then(function(response) {
return response.json();
})
.then(function(data) {
L.geoJSON(data, {
pointToLayer: styles_sites
}).addTo(map);
});
};
I tried the call back method, as advised here
Saving fetched JSON into variable
(EDIT) New code, but there is still a missing formal parameter
function getData("data/sites.geojson", cb) {
fetch("data/sites.geojson")
.then(function(response) {
return response.json();
})
.then(function(data) {
L.geoJSON(data, {
pointToLayer: styles_sites,
onEachFeature: function (feature, layer) {
layer.on('mouseover', function() {
layer.openPopup(layer.bindPopup("<b>"+feature.properties.nombre+"</b>"))
});
layer.on('mouseout', function() {
layer.closePopup();
});
layer.on('click', function () {
layer.bindPopup("<b>Nombre: </b>"+feature.properties.nombre+"<br><b>Barrio: </b>"+feature.properties.barrio+"<br><b>Tipo: </b>"+feature.properties.tipo+"<br><b>Ubicacion: </b>"+feature.properties.ubicacion+"<br><b>Correo: </b>"+feature.properties.contacto);
});
}
}).addTo(map);
.then(function(result) {
cb(result);
});
});
};
getData("data/sites.geojson", function (data) {
return console.log({data});
});

Most probably just incorrect syntax of your callback function:
// Use either arrow function
getData("data/sites.geojson", (data) => {
return console.log({data});
});
// or standard function
getData("data/sites.geojson", function (data) {
return console.log({data});
});

I found the way to work this out by adding within the fetch function, what I originally wanted to do on the map.
This was to add a L.controlLayer using the geojson as overlay.
This is the code that made it work:
let sites = getData()
.then((function(data) {
L.geoJSON(data, {
pointToLayer: styles_sites,
onEachFeature: function LayerControl(feature, layer) {
var popupText = "<b>" + feature.properties.nombre + "<br>";
layer.bindPopup(popupText);
category = feature.properties.tipo;
// Initialize the category array if not already set.
if (typeof categories[category] === "undefined") {
categories[category] = L.layerGroup().addTo(map);
layersControl.addOverlay(categories[category], category);
}
categories[category].addLayer(layer);
layer.on('mouseover', function() {
layer.openPopup(layer.bindPopup("<b>"+feature.properties.nombre+"</b>"))
});
layer.on('mouseout', function() {
layer.closePopup();
});
layer.on('click', function () {
layer.bindPopup("<b>Nombre: </b>"+feature.properties.nombre+"<br><b>Barrio: </b>"+feature.properties.barrio+"<br><b>Tipo: </b>"+feature.properties.tipo+"<br><b>Ubicacion: </b>"+feature.properties.ubicacion+"<br><b>Correo: </b>"+feature.properties.contacto);
});
}
}).addTo(map);
}));
Actually it comes from one of your answer on another post ghybs.

Related

React Displaying List of Items from Ajax request

I am learning React and I am trying to display a list of users from and ajax call. I am getting an unexpected token error from CodePen when I add the line
export default Users;
When I remove the line there are no more errors but the list of users is not being displayed.
My code:
function GetUsers(project){
$.ajax({
url: "https://jsonplaceholder.typicode.com/users",
success: function (data) {
console.log(data);
callback(null, data);
},
error: function (error) {
console.log(data);
callback(error, {});
}
});
}
function UserList(users) {
const userItems = users.map((user) =>
<ul>
<li>
{ user.name }
</li>
<li>
{ user.email }
</li>
<li>
{ user.phone}
</li>
</ul>
);
return (userItems);
}
class Users extends Component {
componentDidMount() {
GetUsers(null, function (err, data) {
if (err)
{
console.log(err);
}// do something
this.setState({ users: data })
}.bind(this))
}
render() {
return(
<UserList user = {this.state.users} />
);
}
}
if (document.getElementById('root')) {
ReactDOM.render(<Users />, document.getElementById('root'));
}
Here is my code.
Thank you for any and all help!
Problem 1 in AJAX call
function GetUsers(project){
$.ajax({
url: "https://jsonplaceholder.typicode.com/users",
success: function (data) {
console.log(data);
callback(null, data);
},
error: function (error) {
console.log(data);
callback(error, {});
}
});
}
$.ajax is asynchronous call, that means it doesn't returns directly any value (how it could if it is fetching the results from the internet) it Just creates another function which will call success and error when completed.
That's why we need to wrap it with callbacks
function GetUsers(project, resolve = () => {}, reject = () => {}) {
}
Problem 2 in mount
componentDidMount() {
GetUsers(null, function (err, data) {
if (err)
{
console.log(err);
}// do something
this.setState({ users: data })
}.bind(this))
}
This code is completely wrong, it has even syntax error so not worth to discuss it in details.
We need to call our new function and pass success callback for mutating the state
GetUsers(null, users => {
this.setState({ users });
});
In this way we will call GetUsers wait for it's results and only after that we will mutate the state with new result
3 problem in component creation
React component's don't have state by default, you need to infer the state from constructor so we need to change initialization to
constructor(props) {
super(props);
this.state = {
users: false
};
}
otherwise you will get Cannot call setState of undefined as state is not automatically created for performance purposes and all components are Pure by default.
I have created a working sandbox here
in
function GetUsers(project){
$.ajax({
url: "https://jsonplaceholder.typicode.com/users",
success: function (data) {
return data;
},
error: function (error) {
console.log(error);
return {};
}
});
}
--
success: function (data) {
return data;
}
doesn't do what you think it does. return data isn't really returning the data... anywhere.
You need to have a callback.
function GetUsers(project, callback){
$.ajax({
url: "https://jsonplaceholder.typicode.com/users",
success: function (data) {
callback(null, data)
},
error: function (error) {
callback(error, {})
}
});
}
class Users extends Component {
componentDidMount() {
GetUsers(null, function (err, data) {
if (err) // do something
this.setState({ users: data })
}.bind(this))
}
render() {
return(
<UserList user = {this.state.users} />
);
}
}
you can also Promise-ify things to simplify the logic

readTextAsync WinJS cannot work

I need to read content from file. I have global variable fileDate and I want to put content to this variable, but when I call load method, the variable is undefined.
var filename = "dataFile.txt";
var fileDate;
WinJS.UI.Pages.define("index.html", {
ready: function (element, options) {
loadDate();
console.log("main" + fileDate);
this.fillYearSelect();
},
function loadDate() {
return localFolder.getFileAsync(filename).then(function (file) {
return Windows.Storage.FileIO.readTextAsync(file).then(function (fileContent) {
fileDate = fileContent;
console.log("fileContent " + fileContent);
},
function (error) {
console.log("Błąd odczytu");
});
},
function (error) {
console.log("Nie znaleziono pliku");
});
}
Sorry for my English :)
Don't forget that javascript is asynchronous, when you call console.log("main" + fileDate), the method loadDate() is not finished, and that is why your fileDate is not defined (yet).
You could use promises to achieve this.
Here is an example based on your code :
var filename = "dataFile.txt";
var fileDate;
var applicationData = Windows.Storage.ApplicationData.current;
var localFolder = applicationData.localFolder;
function loadDate() {
return new Promise(function (onComplete, onError) {
localFolder.getFileAsync(filename).then(function (file) {
Windows.Storage.FileIO.readTextAsync(file).then(function (fileContent) {
fileDate = fileContent;
console.log("fileContent " + fileContent);
onComplete(fileDate);
},
function (error) {
console.log("Error on readTextAsync");
onError(error);
});
},
function (error) {
console.log("Error on getFileAsync");
onError(error);
});
});
}
Now loadDate()returns a promise, you can now use .then() method to do things when loadDate() is finished.
loadDate().then(function (fileDate) {
console.log("Content : " + fileDate);
},
function (error) {
console.log(error);
});

How to work with $resource in angularjs

I am trying to get data form this url http://api.geonames.org/citiesJSON?north=44.1&south=-9.9&east=-22.4&west=55.2&lang=de&username=demo
through $resource below is my resource code
angular.module('myApp.services', ['ngResource']).
value('version', '0.1').factory('recipes1',['$resource', '$http', '$log', function ($resource, $http, $log) {
return $resource('http://api.geonames.org/citiesJSON?north=44.1&south=-9.9&east=-22.4&west=55.2&lang=de&username=demo',{ },{ locate: {method: 'GET', isArray: true, transformResponse: $http.defaults.transformResponse.concat(function(data, headersGetter) {
// probably be better if you examined the results in here
alert(data);
})}
});
}]);
but i am not getting response. i am getting out put from my controller as
function Resource(value){
"use strict";
copy(value || {}, this);
}
Use $http with promise factory:
See working Demo in fiddle
JS
var fessmodule = angular.module('myModule', ['ngResource']);
fessmodule.controller('fessCntrl', function ($scope, Data) {
$scope.runMe = function () {
Data.query($scope.url)
.then(function (result) {
$scope.data = result;
}, function (result) {
alert("Error: No data returned");
});
}
});
fessmodule.$inject = ['$scope', 'Data'];
fessmodule.factory('Data', ['$http','$q', function($http, $q) {
var data = $http({method: 'GET', url: 'http://api.geonames.org/citiesJSON?north=44.1&south=-9.9&east=-22.4&west=55.2&lang=de&username=demo'});
var factory = {
query: function (address) {
var deferred = $q.defer();
deferred.resolve(data);
return deferred.promise;
}
}
return factory;
}]);

Jasmine calling function with ajax returned value

I want to test the "addGroup" function using Jasmine. I get the following error:
Error: Expected spy modifyMyHtml to have been called.at null.
I don't know what is the best way to test the addGroup function. Please HELP.....
var myRecord = {
addGroup: function(groupNumber) {
$.when(myRecord.getHtml())
.done(function(returnedHtml){
myRecord.modifyMyHtml(returnedHtml);
});
},
getHtml: function() {
return $.ajax({url: "myHtmlFile.html", dataType: "html" });
},
// adds options and events to my returned HTML
modifyMyHtml: function(returnedHtml) {
$('#outerDiv').html(returnedHtml);
var myOptions = myRecord.getOptions();
$('#optionsField').append(myOptions);
myRecord.bindEventsToDiv();
},
}
====JASMINE TEST
describe("Configure Record page", function() {
var fixture;
jasmine.getFixtures().fixturesPath = "/test/" ;
jasmine.getFixtures().load("myHtmlFile.html");
fixture = $("#jasmine-fixtures").html();
describe("addGroup", function(){
beforeEach(function() {
var groupNumber = 0;
spyOn(myRecord, "getHtml").andCallFake(function(){
return $.Deferred().promise();
});
spyOn(myRecord, "modifyMyHtml");
myRecord.addGroup(groupNumber);
});
it("Should call getHtml", function() {
expect(myRecord.getHtml).toHaveBeenCalled();
});
it("Should call modifyMyHtml", function() {
expect(myRecord.modifyMyHtml).toHaveBeenCalled(); ==>FAILS
});
});
});
You have to resolve the promise before you return em in your andCallFake.
spyOn(myRecord, "getHtml").andCallFake(function(){
return $.Deferred().resolve ().promise();
});
Btw. you should not test that the function on the object you wanna test are called, but that the html in the DOM are set with the right html
it("Should call modifyMyHtml", function() {
spyOn(myRecord, "getHtml").andCallFake(function(){
return $.Deferred().resolveWith(null, 'returnedHtml').promise();
});
expect($('#outerDiv').html).toEqual('returnedHtml')
});

Node JS - get file via AJAX and then use the data

How do I do this asynchronously?
var getData, myFunc;
getData = function() {
var data = "";
$.get("http://somewhere.com/data.xml", function(d) {
data = $("#selector", d).html();
});
return data; // does not work, because async callback not yet fired
};
myFunc = function() {
var data = getData();
// do something with data here
};
I am happy to completely re-factor to achieve what I want. I am just don't know what design pattern achieves this.
Well, you can't. You can return a promise though:
var getData, myFunc;
getData = function () {
var d = $.Deferred();
$.get("http://somewhere.com/data.xml", function (data) {
d.resolve($("#selector", data).html())
});
return d.promise();
};
getData().then(function (data) {
alert(data);
});
demo http://jsfiddle.net/W75Kt/2/

Resources