Skip to content

Replace 'ajax_caller.js' with JavaScript implementation #2401

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
jeff1evesque opened this issue Feb 21, 2016 · 10 comments
Closed

Replace 'ajax_caller.js' with JavaScript implementation #2401

jeff1evesque opened this issue Feb 21, 2016 · 10 comments

Comments

@jeff1evesque
Copy link
Owner

We will replace our jquery implementation of ajax_caller.js, with a pure javascript implementation. Then, we will remove jquery-2.1.1.js, and ensure 80 character limitation by our jshint, and jscs implementations.

@jeff1evesque
Copy link
Owner Author

We can attempt to implement the following:

@jeff1evesque
Copy link
Owner Author

We should test the following snippet:

...
  }).then(function(response) {
    if (response.ok) {
      // asynchronous callback
      callbackDone(response);
    } else {
      // define error
      var error = new Error(response.statusText);
      error.response = response;
      throw error;
    }
  }, function(error) {
    // asynchronous callback
    callbackFail(error.message, error.response);
  });
...

Specifically, we should test if we can create an arbitrary error.xxx value, within then(function(response) { ... }, and reference it within function(error){ ... }. This way, we can implement a replacement for the following (non-fetch, jquery) implementation:

...
    }).fail(function(jqXHR, textStatus, errorThrown) {

      // asynchronous callback
      callbackFail(textStatus, errorThrown);

    });
...

@jeff1evesque
Copy link
Owner Author

We currently have the following error traceback:

ajax-error

@jeff1evesque
Copy link
Owner Author

We implemented two uncommitted console.log statements within select_session.jsx, to determine if the new FormData was being properly defined:

...
  // send form data to serverside on form submission
    handleSubmit: function(event) {
      // prevent page reload
        event.preventDefault();

      // local variables
        var sessionType = this.state.value_session_type;
        if (
            sessionType == 'data_new' || sessionType == 'data_append' ||
            sessionType == 'model_generate' || sessionType == 'model_predict'
        ) {
            var ajaxEndpoint = '/load-data/';
            var ajaxArguments = {
                'endpoint': ajaxEndpoint,
                'data': new FormData(this.refs.svmForm),
                'contentType': false,
                'processData': false,
            };

console.log(this.refs.svmForm);
console.log(ajaxArguments.data);

          // boolean to show ajax spinner
              this.setState({display_spinner: true});

          // asynchronous callback: ajax 'done' promise
           ajaxCaller(function (asynchObject) {
            // Append to DOM
                if (asynchObject && asynchObject.error) {
                    this.setState({ajax_done_error: asynchObject.error});
                } else if (asynchObject) {
                    this.setState({ajax_done_result: asynchObject});
                }
                else {
                    this.setState({ajax_done_result: null});
                }
            // boolean to hide ajax spinner
                this.setState({display_spinner: false});
            }.bind(this),
          // asynchronous callback: ajax 'fail' promise
            function (asynchStatus, asynchError) {
                if (asynchStatus) {
                    this.setState({ajax_fail_status: asynchStatus});
                    console.log('Error Status: ' + asynchStatus);
                }
                if (asynchError) {
                    this.setState({ajax_fail_error: asynchError});
                    console.log('Error Thrown: ' + asynchError);
                }
            // boolean to hide ajax spinner
                this.setState({display_spinner: false});
            }.bind(this),
          // pass ajax arguments
            ajaxArguments);
        }
    },
...

However, the console.log suggests the FormData is not being created properly:

form-data

Note: we've created a parallel issue to acquire additional input, regarding our implementation of fetch.

@jeff1evesque
Copy link
Owner Author

We checked out the master (functional) branch, and recompiled necessary javascript, along with select_session.jsx. Then, we ensured the same console.log's within select_session.jsx:

...
  // send form data to serverside on form submission
    handleSubmit: function(event) {
      // prevent page reload
        event.preventDefault();

      // local variables
        var sessionType = this.state.value_session_type;
        if (
            sessionType == 'data_new' || sessionType == 'data_append' ||
            sessionType == 'model_generate' || sessionType == 'model_predict'
        ) {
            var ajaxEndpoint = '/load-data/';
            var ajaxArguments = {
                'endpoint': ajaxEndpoint,
                'data': new FormData(this.refs.svmForm),
                'contentType': false,
                'processData': false,
            };

console.log(this.refs.svmForm);
console.log(ajaxArguments.data);

          // boolean to show ajax spinner
              this.setState({display_spinner: true});

          // asynchronous callback: ajax 'done' promise
           ajaxCaller(function (asynchObject) {
            // Append to DOM
                if (asynchObject && asynchObject.error) {
                    this.setState({ajax_done_error: asynchObject.error});
                } else if (asynchObject) {
                    this.setState({ajax_done_result: asynchObject});
                }
                else {
                    this.setState({ajax_done_result: null});
                }
            // boolean to hide ajax spinner
                this.setState({display_spinner: false});
            }.bind(this),
          // asynchronous callback: ajax 'fail' promise
            function (asynchStatus, asynchError) {
                if (asynchStatus) {
                    this.setState({ajax_fail_status: asynchStatus});
                    console.log('Error Status: ' + asynchStatus);
                }
                if (asynchError) {
                    this.setState({ajax_fail_error: asynchError});
                    console.log('Error Thrown: ' + asynchError);
                }
            // boolean to hide ajax spinner
                this.setState({display_spinner: false});
            }.bind(this),
          // pass ajax arguments
            ajaxArguments);
        }
    },
...

which generated the following output within the console.log:

working

@jeff1evesque
Copy link
Owner Author

Currently, all sessions properly functions except when submitting an svm prediction:

prediction

@jeff1evesque
Copy link
Owner Author

We need to implement the following methods, to check whether respective components have mounted:

...
componentDidMount() {
    this.mounted = true;
}

componentWillUnmount() {
    this.mounted = false;
}
...

then, we can check this.mounted, before implementing setState(...) definitions, within the corresponding component definition.

Note: this comment was inspired by the following warning:

warning

@jeff1evesque
Copy link
Owner Author

Our above attempt to resolve the following bug was not successful:

react.min.js:10 Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the ModelGenerate component.

Therefore, we will proceed by opening a dedicated issue to further debug, and resolve the latter bug. This will allow us to return to the main focus of this issue, which currently does not allow dynamic <input> elements to be generated, allowing users to submit their input, for svm prediction.

@jeff1evesque
Copy link
Owner Author

If we adjust ajax_caller.js:

...
  // ajax logic
  fetch(args.endpoint, {
    method: 'post',
    body: args.data,
    headers: {
      'Accept': 'text/javascript'
    }
...

by defining Content-Type:

...
  // ajax logic
  fetch(args.endpoint, {
    method: 'post',
    body: args.data,
    headers: {
      'Accept': 'text/javascript',
      'Content-Type': args.contentType
    }
...

the Make Prediction session will dynamically produce necessary <input> elements, allowing users to submit input values to generate an svm prediction. However, all other sessions, for dataset entry, breaks with our earlier 500 response error:

ajax_caller.min.js:1 POST http://localhost:8081/load-data/ 500 (INTERNAL SERVER ERROR)

So, we need to find a default args.contentType value, which would be equivalent to not defining the Content-Type, when it is not a Make Prediction session:

...
  // set the contentType
  if (args.contentType === null) {
    args.contentType = 'some/value';
  }

  // ajax logic
  fetch(args.endpoint, {
    method: 'post',
    body: args.data,
    headers: {
      'Accept': 'text/javascript',
      'Content-Type': args.contentType
    }
...

@jeff1evesque
Copy link
Owner Author

We forgot to include changes in views.pp.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant