I am currently starting again with Fuse and I am trying to build a simple way to registrate users and log them in.
The user data is stored (and new data also needs to be stored) in a MySQL database on a server.
I already build the basic Fuse structure for entering and getting all the informations but I am struggeling with the server part.
I know that I can not directly connect to my database with Fuse but I am currently a little stuck and curious in whats the best way to implement this.
The part of your question that is related to Fuse is about sending the data to a backend. You should use fetch for making those requests. Since we’re writing the business logic in JavaScript, you will want to send and receive the data in JSON format, which is easily converted to JavaScript types (objects and arrays in particular) and back.
As for your backend, if you have your own custom solution there, you should build a REST API. We have an article about working with REST APIs in Fuse.
The rest concerning your backend is not related to Fuse in any way. You should pick a server-side language you feel most comfortable with (PHP? Python? Something else?) and build that REST API in it. There’s a lot of solutions out there, and I’m certain you could even find a ready-to-roll open source REST API solution somewhere on the internet.
I have now implemented (for basic testings) a simple PHP script, which is returning a JSON encoded response of 2 variables.
The script is working well and returns the response perfectly when testing it with a REST HTTP tool.
I have also implemented the apiFetch function, which you have referred to me.
But this is not working as expected.
The fetch is just returning a Fuse.Scripting.V8.Object.
When wrapping it into a JSON.stringify, it is empty ({}).
Only when I am changing the return of the apiFetch into the following…
Alright, awesome! Happy to see you getting your hands dirty with some backend coding
Looking at the little snippet of code you’re showing, you’re really close to success there. The example in the first link about fetch that I shared goes like this (edited pseudo-code):
fetch(url, object).then(function(response) {
return response.json(); // This returns a promise
}).then(function(responseObject) {
// Do something with the responseObject
console.log(JSON.stringify(responseObject));
}).catch(function(err) {
// An error occurred somewhere in the Promise chain
});
So I guess you’re missing a second .then() in the chain, and a return response.json(); in the first .then() handler.
// Fetch the resource and parse the response as JSON
return fetch(url, options)
.then(function(response) {
// This returns a promise
return response.json();
})
.then(function(responseObject) {
// Do something with the responseObject
console.log(JSON.stringify(responseObject));
return responseObject;
}).catch(function(err) {
// An error occurred somewhere in the Promise chain
console.log("Error");
});
The log of the responseObject in the second then is giving me the correct response.
To work with the response, I tried to return the response (as you can see in the second then).
I call it just like in the “Working with REST APIs” example:
var apiJSON = testApi();
console.log(JSON.stringify(apiJSON));
}
function testApi(){
return apiFetch("api");
}
This is my complete apiFetch:
function apiFetch(path, options) {
var url = encodeURI(ROOT_URL + path);
if(options === undefined) {
options = {};
}
// If a body is provided, serialize it as JSON and set the Content-Type header
if(options.body !== undefined) {
options = Object.assign({}, options, {
body: JSON.stringify(options.body),
headers: Object.assign({}, options.headers, {
"Content-Type": "application/json"
})
});
}
// Fetch the resource and parse the response as JSON
return fetch(url, options)
.then(function(response) {
// This returns a promise
return response.json();
})
.then(function(responseObject) {
// Do something with the responseObject
console.log(JSON.stringify(responseObject));
return responseObject;
}).catch(function(err) {
// An error occurred somewhere in the Promise chain
console.log("Error");
});
}
The log of the fetch is working.
But I am still getting an empty Object when I try to access it from outside (my apiJSON var).
Its almost working but I am obviously still missing something.
I see your point.
I am not very familiar with the async stuff, so it’s quite new to me and I was not aware of the promise thing.
What possibilities do I have in converting the promise into a variable?
For example, like in the “Working with REST APIs” example, when I fetch some articles.
I am not sure about how I can continue there.
I fetched them but somehow I need to store them to work with them?
The answer to that is Observables. You can’t really convert a promise to something else; it’s just that - a promise, that either resolves with a result, or rejects with an error. The key is to do something when a promise resolves.
That same example I referred to above shows how you populate the articles Observable from the fetch promise:
var Observable = require("FuseJS/Observable");
var API = require("api");
var articles = Observable();
function refreshArticles() {
API.getAllArticles().then(function(newArticles) {
articles.replaceAll(newArticles);
});
}
refreshArticles();
module.exports = {
articles: articles,
refreshArticles: refreshArticles
}
Alright, there’s several issues. Here you go, hunted them all down (see my comments):
<App>
<!-- Imports -->
<JavaScript>
var Observable = require('FuseJS/Observable');
var response = Observable();
var button = function(){
testApi();
// console.log would execute before testApi() finishes...
// ...you can't expect response to have changed here. it's async!
//console.log(JSON.stringify(response)); // do not do this
}
function testApi(){
apiFetch("api").then(function(newResponse){
console.log("got response from apiFetch: " + JSON.stringify(newResponse));
// would you look at that... it is an object! such object: {"id":"50","message":"this is a test-return"}
// response.replaceAll(newResponse); // .. but replaceAll() expects an array, not an object :(
// so we could just make an array for it
// ... although it does not make much sense if you ask me, but hey...
// ...if you want to put a single object in an observable list, you can totally do that!
var tmp = []; // so then, make an array
tmp.push(newResponse); // push the response object in it (now the array holds a single item, that object)
response.replaceAll(tmp); // and finally call the replaceAll with the array
});
}
var ROOT_URL = "https://www.rwtravelbuddy.de/";
function apiFetch(path, options) {
var url = encodeURI(ROOT_URL + path);
if(options === undefined) {
options = {};
}
// If a body is provided, serialize it as JSON and set the Content-Type header
if(options.body !== undefined) {
options = Object.assign({}, options, {
body: JSON.stringify(options.body),
headers: Object.assign({}, options.headers, {
"Content-Type": "application/json"
})
});
}
// Fetch the resource and parse the response as JSON
return fetch(url, options)
.then(function(response) {
// This returns a promise
return response.json();
})
.then(function(responseObject) {
// Do something with the responseObject
console.log("Log from the apiFetch-Function:" + JSON.stringify(responseObject));
return responseObject;
}).catch(function(err) {
// An error occurred somewhere in the Promise chain
console.log("Error");
});
}
module.exports = {
button: button,
response: response // of course we also need to make the observable available to UX code
}
</JavaScript>
<StackPanel Margin="50">
<Button Text="Click to test API" Background="#f2f2f2" Clicked="{button}"/>
<!-- since response is a list (well, you wanted it to be, right?), we must use an Each to iterate over it -->
<Each Items="{response}">
<Text Value="{message}" />
</Each>
</StackPanel>
</App>
Is there something I am missing when working with different methods?
I tried to use methods like Post and Put but somehow I just seem to run into the catch.
I tried it like in the publishArticle example:
function testApi(){
apiFetch("api", {
method: "POST"
}).then(function(newResponse){
console.log("got response from apiFetch: " + JSON.stringify(newResponse));
var tmp = [];
tmp.push(newResponse);
response.replaceAll(tmp);
});
}
With the server, I am sending a response for POST requests (just for testing) but somehow just the GET requests are working.