Building a Log-In and Registration

Hi guys,

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.

Can you help me here?

Hi Jxns.

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.

Hope this helps!

Thank you for your reply!

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…

     return fetch(url, options)
	.then(function(response) { console.log(JSON.stringify(response)); });

… I can see the response.
But even then I cannot assign it to a variable and access it again.

Any idea what I did wrong?

Thats the quick code I used to test the assignment, but it seems to be an empty Fuse.Scripting.V8.Object.

var login = function(){
    var x = apiFetch("api");
}

Alright, awesome! Happy to see you getting your hands dirty with some backend coding :slight_smile:

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.

Hope this helps!

Alright, its almost working.

Like you said, I changed it to this way:

       // 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.

It’s async. What you’re missing is that you’re returning a Promise.

So when you do:

var apiJSON = testApi();
console.log(JSON.stringify(apiJSON));

then apiJSON is a promise, not the result of it.

You should do this instead:

testApi().then(function(result) {
    console.log(JSON.stringify(result));
});

If you scroll down to the last example there on the “Working with REST APIs” page, right before “OAuth2” header, you’ll see the same approach:

API.getAllArticles().then(function(newArticles) {
    articles.replaceAll(newArticles);
});

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
}

Somehow I am still struggeling with this.

I have created an Observable.

var response = Observable(); 

And created the function to update my response-observable.

  function testApi(){
    apiFetch("api").then(function(newResponse){
      response.replaceAll(newResponse);
    });
  }

But my Observable is, again, an empty object.

Can you help me out again?

I’m sure I can, but please post a complete, minimal reproduction. Think of it as a single-UX-file app that one could copy-paste and run.

That would be great.

I’ve created a quick app and pushed it to GitHub, so you can just download and test it.

I hope you can find where my mistake is.

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>

Thank you for helping me here!

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.

That’s something you need to check with your backend.

Here, I changed one line to: console.log("Error: " + err.message); and got this in log: console.log("Error: " + err.message);.

That tells me that your backend is returning some sort of HTML (which usually starts with < as you might know).

You’re right, I was wondering about that error too.
But the response of my backend is the same like in the GET-request.

This response should be okay. I also checked it with a REST-Tool and got a similar response (just like the GET response).

Is my backend really the issue here?

Yes, it is your backend, it responds with error 500.

So if you add some more logging in your code:

return fetch(url, options)
    .then(function(response) {
    // This returns a promise
    console.log(JSON.stringify(response));

You can see the whole response object:

[Viewport]: {"type":"default","status":500,"ok":false,"statusText":"Internal Server Error","headers":{"map":{"date":["Wed, 06 Dec 2017 13:01:28 GMT"],"content-type":["text/html; charset=UTF-8"],"content-length":["7660"],"connection":["keep-alive"],"server":["Apache"],"cache-control":["private, must-revalidate"],"x-content-type-options":["nosniff"],"referrer-policy":["no-referrer-when-downgrade, strict-origin-when-cross-origin"],"pragma":["no-cache"],"expires":["-1"],"x-frame-options":["SAMEORIGIN"],"x-xss-protection":["1; mode=block"],"set-cookie":["PHPSESSID=r2j7s6uldd86e36v46m0hk5225; path=/; HttpOnly"]}},"url":"","_bodyInit":".............