I have a model and I am trying to fetch it using model.fetch();. The model's urlRoot set to the back-end of my application ("/backend/item"), but right now I don't have the back-end environment. So I decided to mock the results. I added a route inside my router:
"backend/item/:id": "data_getItem"
and a function:
data_getItem: function(id) {
console.log("data_getItem: "+ id);
return {
animals: [
{
name: 'flying cat',
type: 'none'
}
]
};
}
When running the application I can see ajax call to "http://127.0.0.1:8000/backend/item/1" but the console is empty and I get an error (the fetch function returns me to the error callback). Why is that? How can I mock the back-end?
EDIT
Actually #rjz helped me with the things I want to do, but I really want to know if an ajax call can be catched by backbone router.
My intuition tells me not because ajax call cannot execute backbone client code and therefore the router concept is not relevant. Am I right?..
I don't think you want to use a Backbone.Router to catch your AJAX calls. If your goal is mocking out the backend of your project, you should use a testing framework to do this. A down and dirty way would be to use something like:
mock-ajax
jquery-mockajax
or if you want to do something more like unit testing I would look at Jasmine and its AJAX mocking library.
Update to answer your question:
The short answer is no, a Backbone.Router cannot intercept AJAX calls.
This is because the router works by listening to events that have to do with the URL. Specifically, the router is listening to the hashchange or popstate events (depending on if you are using pushState). Since AJAX calls do no interact with the URL they pretty much totally bypass this system.
Related
I'm learning about TDD React here and don't understand the below test situation:
it('Correctly updates the state after AJAX call in `componentDidMount` was made', (done) => {
nock('https://api.github.com')
.get('/users')
.reply(200, [
{ 'name': 'Reign', 'age': 26 }
]);
// Overwrite, so we can correctly reason about the count number
// Don't want shared state
wrapper = mount(<UsersListComponent />);
setTimeout(function() {
expect(wrapper.state().usersList).to.be.instanceof(Array);
expect(wrapper.state().usersList.length).to.equal(1);
expect(wrapper.state().usersList[0].name).to.equal('Reign');
expect(wrapper.state().usersList[0].age).to.equal(26);
nock.cleanAll();
done();
}, 1500);
});
What is the purpose of using nock to fake a request? This request doesn't do anything and I'm not sure where the response goes to. I thought TDD approach is to write the test (the code starting at wrapper), see it fail, and then use a real ajax call in the actual component to test. I don't see what nock does here.
The purpose of the nock call in your code is to fake an API request. Nock captures / intercepts the call and instead of the actual response it returns a response with fake information.
The title of the test is Correctly updates the state after AJAX call... so the intention is to test whether the state is updated correctly, and not whether the actual API request has been successfully carried out.
This allows you to model and test different scenarios, for example, how your app behaves when receiving different datasets. It also allows you to complete your tests when the actual API may not be ready yet.
The purpose of Unit Testing is to be only testing your code is the most isolated way possible. Faking an AJAX request and getting its responses is a very common practice to avoid issues with your endpoint (since this is not what you are testing anyway) and focusing on the code handling the response of this endpoint, and you can choose different models of response to test different scenarios.
Nock will simply feed the response back to your component when your call to 'https://api.github.com/users' is made
I'm working on my local development environment using angular to issue ajax calls to Web.API (IIS 8.5 hosted). I'm making 5 calls via different angular controllers simultaneously, each of which look like this:
$scope.medications = API.Client.MedicationProfiles.query({ clientId: clientId });
The API service has this definition for the Client.MedicationProfiles resource:
this.Client.MedicationProfiles = $resource(
'/Noteable.API/api/Client/:clientId/MedicationProfiles/:id',
{
clientId: '#clientId',
id: '#Id'
},
{
update: { method: 'PUT' }
}
);
I can see all of the requests going to the server basically at once using the chrome dev tools as the page loads but it appeared that they were coming back one at a time as if they had been run synchronously. I put a thread.sleep in one of the Web.API controller actions and sure enough, all calls issued after that one fail to return until the sleeping one does. This doesn't make any sense to me and I'm wondering if someone can tell me in what case they would expect this.
This may be a good situation to implement an asynchronous pattern on your web api backend - you'll be alleviated from your ajax calls blocking once they hit your controller. This can be achieved by leveraging an async and await pattern. You'll want to return a Task, which represents an asynchronous operation.
An example may include...
public async Task<IHttpActionResult> Put(string clientId)
{
var response = await this.yourService.yourSavingMethod(clientId);
return Ok(response);
}
Also see SO question Why is this web api controller not concurrent? for more details and insight on the issue. Furthermore, the default behavior for ASP.NET Session State and can be changed to accommodate concurrent requests. An example may include
HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.ReadOnly)
ASP.NET Session State Overview
I think your problem is caused either by browser or ASP.NET. In case it's ASP.NET, take a look at this thread:
C# Web API - Blocking
In case it's your browser, take a look at this thread with example code:
Why is my async ASP.NET Web API controller blocking the main thread?
I'm developing extension to an existing app using expressjs. By requirements I need to do server side rendering. Our API server is running on JAVA.
In my express app, I'm going to have to render page while making serverside calls to JAVA server. For example, I'm going to call getCategories, getVendors, getReviews etc APIs in order get data that I need to pass to rendering template.
What is a good way to accomplish this? I mean pack all of that into a single object and pass to res.render() method. Could you please provide me with some basic examples? I imagine that I would need to create a module that does all of this and returns some nice object...
All of the examples on the internet show something like res.render('index', { data: 'someData'}), however in this case data is bootstrapped. I would need a data to be compiled with several API calls and then passed to the rendering method.
Thanks!
It really depends on whether you want to call your Java API server side or client side.
If server side, your express route containing res.render() will need to collect all the information it needs from Java before rendering the page. If your API is slow, the page load will be slow. If possible, use something like async.parallel to avoid blocking.
Your code sample is correct. res.render('index', { foo: 'bar'})
This would add the foo variable to the root scope of your view. How you build up the data structure is entirely up to you. I would recommend using async.parallel and/or async.series to collate all of the data. If they are all completely independent, run them in parallel.
// an example of how to run each in parallel and then render the view.
var getCategories = function(done) {
// get something
done();
};
var data = {};
async.parallel([
getCategories, // <-- adds to the data structure
getVendors,
getReviews
], function(err) {
res.render('index', { data: data });
});
Your other option is using express to render the base page and using something like jQuery to hit the Java API and update the relevant page fragments.
I'm working in a team split into front-end and back-end developers. Sometimes, the front-end wants to make some REST requests to a http address / REST-resource that isn't yet implemented.
In ngMockE2E there's a $httpBackend service that seems quite useful for this. The question is, how do I mock only some specific urls/rest resources?
I want most requests like e.g. GET /users.json to go through to the backend server as usual. But while waiting for e.g. GET /users/tommy/profile.json to get implemented (by the back-end guys), it would be nice to have some "pretend response", aka mocking, so we can keep working. How should one go about?
Thanks :)
try include this in your project:
app.config(function($provide) {
$provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);
}).run(function($httpBackend) {
// make sure we have access to
$httpBackend.whenGET('*').passThrough();
// here use your mocking data using $httpBackend
});
I have been experimenting with the localstorage module for Backbone.js (https://github.com/jeromegn/Backbone.localStorage). As I understand it this overloads Backbone.sync and therefore stops backbone from pushing to the server(?). Ideally, I would like pass my data back to the server as well and persist it locally when online and just use localstorage when offline (you know, the perfect app). I haven't found any documentation yet.
Is Backbone.localStorage a part of this?
Has anyone been able to build this scenario?
How is this done? (Please tell me I don't have to roll my own.)
Thanks.
Backbone.localStorage is an external file you can use which overwrites Backbone.Sync.
You can use simple feature detection for whether the user is offline or online and then asynchronously load Backbone.localStorage.js if they are offline.
If neccesary you can also pass in a specific version of Backbone.sync to your models and collections.
If you want to do both at the same time you'll have to write your own version of Backbone.sync that both calls the server and calls localStorage.
The easiest way to do this is to just define
Backbone.sync = function() {
originalSync.apply(this, arguments);
localStorageSync.apply(this, arguments);
}
Edit:
As mentioned in the comments, if you use the latest backbone localStorage plugin then you can do the following
Backbone.sync = function Sync() {
Backbone.ajaxSync.apply(this, arguments);
return Backbone.localSync.apply(this, arguments);
};