angular $http service singleton clash - ajax

$http service in angular is singleton, and my previous experience with xhr/ ajax request shown to have clash when two request share the same xhr object. Should it not a problem with angular ? if yes how angular handles such situation ?

I think you're misunderstanding the fact that the $http service is a singleton to mean that all requests somehow will share the same XHR object. They don't.
The $http service itself is a singleton, but that doesn't mean that the requests share the same XHR object.
Anytime you call an $http service method (for example, $http#get), it initializes a new asynchronous request... However, it doesn't initialize a new $http object.
Take a look at some of Addy Osmani's sample code for the singleton pattern:
return {
getInstance: function () {
if ( !instance ) {
instance = init();
}
return instance;
}
};
The singleton pattern simply ensures that a new instance of the $http service itself doesn't get initiliazed over and over again... But it doesn't mean there is just one XHR object.
The pseudo-code for the $http service would look something like this:
var $httpProvider = (function() {
var somePrivateConfig = "something important";
var service = {
request: function() {
// make an HTTP request with an XHR object
}
};
return {
init: function() {
// this is the important part that makes sure its a singleton
window.$http = window.$http || service;
}
};
})();
/**
* Something like this would be called whenever you
* inject the $http service as a dependency...
* However, since it could be passed into multiple things all in the same runtime,
* like controllers, directives, etc., we only need to initialize it ONE time
*/
$httpProvider.init();
/**
* Now let's pretend we're inside, say, a controller.
*
* This method can safely be called many times,
* but the method is always being called from the same singleton object
*/
$http.request();
Also, you'll notice that there's a local variable somePrivateConfig within the $httpProvider IIFE. If we were to re-initialize a new $http every time its injected to a component (whether that's a controller, directive, or whatever), a new private variable would be created, but we always want to be referencing that same value throughout the lifecycle of the $http object, so that we can guarantee that all those components are always referencing the same information.
But this has nothing to do with the XHR object itself. I may have misused some of the terminology above and misrepresented where and how providers themselves within the context of AngularJS are initialized into singleton objects, but the principle of the singleton pattern still stands in that it simply means the async request wrapper "class" (which is the $http service) is a singleton, but the XHR isn't.

$http requests are async and return a promise with methods success() and error(). Below more information ($q service, which is an implementation of promises by Angularjs):
"A service that helps you run functions asynchronously, and use their return values (or exceptions) when they are done processing"
Read here:
https://docs.angularjs.org/api/ng/service/$http
https://docs.angularjs.org/api/ng/service/$q

Related

How to register a mock object in Service Container testing

I need to register a object to the service container.
I tried with the following code but I get
Error Call to undefined method ::process()
$o = $this->instance(Service::class, Mockery::mock(Service::class, function ($mock) {
$mock->shouldReceive('process')->once()->andReturn(10);
}));
$this->app->instance(Service::class, $o);
dd((new Service())->process());
Firstly for mocking an object, this should suffice. The middle step is not required.
$this->instance(Service::class, Mockery::mock(Service::class, function ($mock) {
$mock->shouldReceive('process')->once()->andReturn(10);
}));
For your mock to load, you have to get it out through the container, you have recently bound it with the container. There are many ways of doing this, $this->app->instance(), app(), resolve() etc.
dd($this->app->instance(Service::class)->process());

mocha: can't use one request for mutlple `it` test

const request = require('supertest');
const server = request('http://localhost:9001');
describe('Get /static/component-list.json', function() {
const api = server.get('/static/component-list.json');
it('should response a json', function(done) {
api.expect('Content-Type', /json/, done);
});
it('200', function(done) {
api.expect(200, done); // This will failed
// server.get('/static/component-list.json').expect(200, done); // This will successed
});
});
when reuse api in the second test case, mocha will raise a Error:
The result of mocha test/api command:
How can I request the url once and use in multiple it case.
Solution
You have to create a new request for each test (each it) that you want to run. You cannot reuse the same request for multiple tests. So
describe('Get /static/component-list.json', function() {
let api;
beforeEach(() => {
api = server.get('/static/component-list.json');
});
Or if you want to reduce the number of requests made, then combine all your checks on the request into a single Mocha test.
Explanation
If you look at the code of supertest, you'll see that when you call an expect method with a callback, expect calls automatically calls end. So this:
api.expect('Content-Type', /json/, done);
is equivalent to this:
api.expect('Content-Type', /json/).end(done);
The end method is provided by superagent, which is what supertest uses to perform requests. The end method is what kicks off the request. It means you are done setting up the request and want to fire it off now.
The end method calls the request method, which is tasked with using Node's networking machinery to produce a Node request object that is used to perform the network operation. The problem is that request caches the Node request is produces but this Node request object is not reusable. So ultimately, a superagent or supertest request cannot be ended twice. You have to reissue the request for each test.
(You could manually flush the cached object between tests by doing api.req = undefined. But I strongly advise against this. For one thing, whatever optimization you might think you'd get is minimal because the network request still has to be made anew. Secondly, this amounts to messing with superagent's internals. It may break with a future release. Third, there may be other variables that hold state that might need to be reset together with req.)

AngularJS: Setting Global Variable AJAX

I am looking for best practices with AngularJS:
I need to share a json ajax response between nested controllers.
Controller1->Controller2->Controller3
Right now I have a working version that simply sets a $scope.variable with the response in controller1, and the other controllers access it by calling the same variable.
I have tried creating a global service, but the problem is I make the ajax call in a controller, and before the ajax call is finished, the global variable defaults to null for all the other controllers.
I am just trying to understand what best approach is in this situation.
Thanks
Create publisher/subscriber service or factory and subscribe methods from your controller2 and 3 to data change. Just like this:
angular
.module('')
.factory('GlobalAjaxVariable', function() {
var subscribers = [];
function publish(data) {
callbacks.forEach(function(clb) {
clb(data);
});
}
return {
setData: function(ajaxData) {
publish(ajaxData);
},
addSubscriber: function(clb) {
subscribers.push(clb);
}
};
});
You can put the value in $rootScope.variable and after access it from any other controller (as $scope.variable)

symfony2 my own event

I made the authorization and authentication via facebook like here:
http://symfony.com/doc/current/cookbook/security/custom_authentication_provider.html
and it works
Now I want to make my own event, this event will do something when the user authenticates using facebook. For example-will redirect the user to the home page.
I did it like this
http://symfony.com/doc/current/components/event_dispatcher/introduction.html
So I have this class
http://pastebin.com/2FTndtL4
I do not know how to implement it, what am I supposed to pass as an argument to the constructor
It's really simple. Symfony 2 event system is powerful, and service tags will do the job.
Inject the dispatcher into the class where you want to fire the event. The service id is event_dispatcher;
Fire the event with $this->dispatcher->dispatch('facebook.post_auth', new FilterFacebookEvent($args)) when needed;
Make a service that implements EventSubscriberInterface, defining a static getSubscribedEvents() method. Of course you want to listen to facebook.post_auth event.
So your static method will look like:
static public function getSubscribedEvents()
{
return array(
'facebook.post_auth' => 'onPostAuthentication'
);
}
public function onPostAuthentication(FilterFacebookEvent $event)
{
// Do something, get the event args, etc
}
Finally register this service as a subscriber for the dispatcher: give it a tag (eg. facebook.event_subscriber), then make a RegisterFacebookEventsSubscribersPass (see this tutorial). You compiler pass should retrieve all tagged services and inside the loop should call:
$dispatcher = $container->getDefinition('event_dispatcher');
$subscribers = $container->findTaggedServiceIds('facebook.event_subscriber');
foreach($subscribers as $id => $attributes) {
$definition->addMethodCall('addSubscriber', array(new Reference($id)));
}
This way you can quick make a subscriber (for logging, for example) simply tagging your service.
Event object is just some kind of state/data storage. It keeps data that can be useful for dispatching some kind of events via Subscribers and/or Listeners. So, for example, if you wanna pass facebook id to your Listener(s) - Event is the right way of storing it. Also event is the return value of dispatcher. If you want to return some data from your Listener/Subscriber - you can also store it in Event object.

how to create a new AJAX object using Prototype

How can i create a new Ajax object everytime for a particular ajax request, using Prototype library? It seems in Prototype, "Ajax" is a global object and all reqs are its instances. Please help..
Thanks
Actually, Prototype creates a new "instance" for each request. You do it like this:
var request = new Ajax.Request('/your/url', {
onSuccess: function(transport) {
// yada yada yada
}
});
Normally you skip the "var request = " part, unless you need access to the public properties of the instance. One possible reason would be to access the "transport" property which contains the "raw" XMLHttpRequest object.

Resources