API calls in angularJS right after each other - javascript

I have a problem using angular in a Ionic mobile project , I have this piece of code working great in my desktop environment. I do three API call to a web server 500ms after each other. But in the phone using a lower connection sometimes one of the call fails so the whole process fail.
Is there some way to do the API calls in the exact moment that the previous one finish? I mean, not using fixed amount of time.
//get member information
$timeout(function() {
membersService.getMember(community.url, community.user.api_key, community.user.auth_token, $stateParams.userId).
success(function(data) {
$scope.member = data.result;
});
}, 500);
$timeout(function() {
messagesService.getConversation(community.url, community.user.api_key, community.user.auth_token, community.user.user_info.guid, $stateParams.userId, "from").
success(function(data) {
if(data.result["entities"].length > 0) {
messages = messages.concat(data.result["entities"]);
subject = "Re: "+data.result["entities"][data.result["entities"].length-1].title;
}
$scope.messageData.subject = subject;
});
}, 1000);
$timeout(function() {
messagesService.getConversation(community.url, community.user.api_key, community.user.auth_token, community.user.user_info.guid, $stateParams.userId, "to").
success(function(data) {
log = [];
if(data.result["entities"].length > 0) {
angular.forEach(data.result["entities"], function(v, k) {
v.owner_guid = $stateParams.userId;
log.push(v);
}, log);
messages = messages.concat(log);
}
var log = [];
var count = 0;
angular.forEach(messages, function(v, k) {
messages_reorder.push(v);
}, log);
});
}, 1500);

This was the result of implementing nesting promise chains:
var loadMemberInfo = function( userId )
{
return membersService
.getMember(community.url, community.user.api_key, community.user.auth_token, $stateParams.userId)
.then(function(data)
{
$scope.member = data.result;
});
},
getConversationFrom = function() {
return messagesService
.getConversation(community.url, community.user.api_key, community.user.auth_token, community.user.user_info.guid, $stateParams.userId, "from")
.then(function(cf) {
if(cf.data.result["entities"].length > 0) {
messages = messages.concat(cf.data.result["entities"]);
subject = "Re: "+cf.data.result["entities"][cf.data.result["entities"].length-1].title;
}
$scope.messageData.subject = subject;
});
},
getConversationTo = function() {
messagesService
.getConversation(community.url, community.user.api_key, community.user.auth_token, community.user.user_info.guid, $stateParams.userId, "to")
.then(function(ct) {
log = [];
if(ct.data.result["entities"].length > 0) {
angular.forEach(ct.data.result["entities"], function(v, k) {
v.owner_guid = $stateParams.userId;
log.push(v);
}, log);
messages = messages.concat(log);
}
//order array
messages = messages.sort(function(a,b) { return a.time_created - b.time_created } );
var log = [];
var count = 0;
angular.forEach(messages, function(v, k) {
messages_reorder.push(v);
}, log);
});
},
orderFullConversation = function() {
$ionicLoading.hide();
console.log(messages);
if(messages_reorder.length > 5) {
var messages_partial = messages_reorder.slice(messages_reorder.length-5,messages_reorder.length);
}
else {
var messages_partial = messages_reorder;
}
$scope.messages = messages_partial;
$scope.community = community;
};
loadMemberInfo( $stateParams.userId )
.then( getConversationFrom )
.then( getConversationTo )
.then( orderFullConversation );
More details here

You can use angular $q service for that.

You should look at the Angular Promise API. it is meant for the same purpose. It allows you to chain ajax calls one after another..
// this
$http.get('/api/v1/movies/avengers')
.success(function(data, status, headers, config) {
$scope.movieContent = data;
});
// is the same as
var promise = $http.get('/api/v1/movies/avengers');
promise.then(
function(payload) {
$scope.movieContent = payload.data;
});
More Details here

Related

Mocking service when testing controller in Karma for angularjs

I am working on the Single Page Application with AngularJS project for the Treehouse Full Stack JavaScript TechDegree and I am trying to do unit tests on the controllers. To test the controllers that make api calls to the dataService I have to mock the dataService and I can not figure out how to do this correctly. I have read article after article on unit testing angular and I am so lost that I have no idea what to do next.
controllers.js:
(function() {
'use strict';
angular.module('app')
.controller('RecipesController', function(dataService,$location) {
const vm = this;
vm.init = () => {
vm.hidden = true;
dataService.getAllRecipes(function(response) {
vm.recipes = response.data;
vm.getCategories(response.data);
});
}
vm.selectCategory = (category) => {
if (category === null) {
vm.init();
} else {
dataService.getCategory(category,function(response) {
vm.recipes = response.data;
});
}
};
vm.getCategories = (data) => {
let categories = new Set();
for (let item of data) {
categories.add(item.category);
}
vm.categories = Array.from(categories);
};
vm.addRecipe = () => {
$location.path('/add');
}
vm.deleteRecipe = (recipe,$index) => {
vm.toDelete = recipe.name;
vm.hidden = false;
vm.deleteIt = () => {
vm.hidden = true;
dataService.deleteRecipe(recipe._id,function(response) {
vm.init();
});
}
}
vm.init();
})
.controller('RecipeDetailController', function($scope,dataService,$location) {
const vm = this;
const init = () => {
const path = $location.path();
if (path.includes("edit")) {
let id = path.slice(6);
dataService.getID(id,function(response) {
vm.recipe = response.data;
vm.title = response.data.name;
vm.editCategory = response.data.category;
});
} else if (path.includes("add")) {
vm.recipe = {
name: "",
description: "",
category: "",
prepTime: 0,
cookTime: 0,
ingredients: [
{
foodItem: "",
condition: "",
amount: ""
}
],
steps: [
{
description: ""
}
]
}
vm.title = 'Add New Recipe.'
}
dataService.getAllCategories(function (response) {
vm.categories = response.data;
let index = response.data.findIndex(item => item.name === $scope.editCategory);
if (index === -1) {
vm.initial = {"name": "Choose a Category"};
} else {
vm.initial = $scope.categories[index];
}
});
dataService.getAllFoodItems(function (response) {
vm.foods = response.data;
});
}
vm.addItem = (item) => {
if (item === 'ingredient') {
vm.recipe.ingredients.push({amount: "amount", condition: "condition", foodItem: ""});
} else if (item === 'step') {
vm.recipe.steps.push({description: "description"});
}
};
vm.deleteItem = (item,$index) => {
if (item === 'ingredient') {
vm.recipe.ingredients.splice($index,1);
} else if (item === 'step') {
vm.recipe.steps.splice($index,1);
}
}
vm.saveChanges = (recipe) => {
vm.errors = [];
const buildErrorArray = (errorArray) => {
for (let item of errorArray) {
vm.errors.push(item.userMessage);
}
}
const collectErrors = (response) => {
if (response.data.errors.category) { buildErrorArray(response.data.errors.category) }
if (response.data.errors.ingredients) { buildErrorArray(response.data.errors.ingredients) }
if (response.data.errors.name) { buildErrorArray(response.data.errors.name) }
if (response.data.errors.steps) { buildErrorArray(response.data.errors.steps) }
}
if (recipe._id) {
dataService.updateID(recipe,function(response) {
$location.path('/');
}, function(response) {
collectErrors(response)
});
} else {
dataService.addRecipe(recipe,function(response) {
$location.path('/');
}, function(response) {
collectErrors(response)
});
}
}
vm.cancelChanges = () => {
$location.path('/');
}
init();
});
}());
services.js:
(function() {
'use strict';
angular.module('app')
.service('dataService', function($http,errors,httpErrors) {
this.getAllRecipes = function (callback) {
$http.get('http://localhost:5000/api/recipes')
.then(callback,httpErrors.display('HTTP Error'))
.catch(errors.catch());
};
this.getAllCategories = function (callback) {
$http.get('http://localhost:5000/api/categories')
.then(callback,httpErrors.display('HTTP Error'))
.catch(errors.catch());
};
this.getAllFoodItems = function (callback) {
$http.get('http://localhost:5000/api/fooditems')
.then(callback,httpErrors.display('HTTP Error'))
.catch(errors.catch());
};
this.getCategory = function(category,callback) {
$http.get('http://localhost:5000/api/recipes?category=' + category)
.then(callback,httpErrors.display('HTTP Error'))
.catch(errors.catch());
};
this.getID = function (id,callback) {
$http.get('http://localhost:5000/api/recipes/' + id)
.then(callback,httpErrors.display('HTTP Error'))
.catch(errors.catch());
};
this.updateID = function (data,success,error) {
$http.put('http://localhost:5000/api/recipes/' + data._id, data)
.then(success,error).catch(errors.catch());
};
this.addRecipe = function (data,success,error) {
$http.post('http://localhost:5000/api/recipes', data)
.then(success,error).catch(errors.catch());
};
this.deleteRecipe = function (id,callback) {
$http.delete('http://localhost:5000/api/recipes/' + id)
.then(callback,httpErrors.display('HTTP Error'))
.catch(errors.catch());
};
});
}());
controllersSpec.js:
describe("Unit Testing Controllers", function() {
beforeEach(angular.mock.module('app'));
let $scope;
let getAllRecipesMock;
beforeEach(inject(function(_$controller_,_$rootScope_,$q) {
$controller = _$controller_;
$scope = _$rootScope_.$new();
getAllRecipesMock = {
getAllRecipes: function() {
var deferred = $q.defer();
deferred.resolve([{name: "recipename"}]);
return deferred.promise;
}
}
}));
it('has a test to test that tests are testing', function() {
expect(2 + 2).toEqual(4);
});
it('should have a RecipesController', function() {
const controller = $controller('RecipesController',{$scope:$scope});
expect(controller).toBeDefined();
});
it('should have a RecipeDetailController', function() {
const controller = $controller('RecipeDetailController',{$scope:$scope});
expect(controller).toBeDefined();
});
it('should call the getAllRecipes service and return response', inject(function() {
const controller = $controller('RecipesController',{$scope:$scope,dataService:getAllRecipesMock});
$scope.$digest();
expect(controller.recipes).toBe([{name: "recipename"}]);
}));
it('should remove duplicate categories', function() {
const controller = $controller('RecipesController',{$scope:$scope});
let data = [{'category':'dog'},{'category':'cat'},{'category':'horse'},{'category':'dog'},{'category':'cow'}];
controller.getCategories(data);
expect(controller.categories).toEqual(['dog','cat','horse','cow']);
});
it('should take you to the /add route when the addRecipe method is called', inject(function($location) {
const controller = $controller('RecipesController',{$scope:$scope});
controller.addRecipe();
expect($location.path()).toEqual('/add');
}));
});
This is the result I get when I run the tests:
Unit Testing Controllers
√has a test to test that tests are testing
√should have a RecipesController
√should have a RecipeDetailController
×should call the getAllRecipes service and return response
Expected undefined to be [ Object({ name: 'recipename' }) ].
at Object.<anonymous> (test/controllersSpec.js:38:32)
at Object.invoke (node_modules/angular/angular.js:4839:19)
at Object.WorkFn (node_modules/angular-mocks/angular-mocks.js:3155:20)
√should remove duplicate categories
√should take you to the /add route when the addRecipe method is called
Chrome 55.0.2883 (Windows 10 0.0.0): Executed 6 of 6 (1 FAILED) (0.235 secs / 0.084 secs)
TOTAL: 1 FAILED, 5 SUCCESS
1) should call the getAllRecipes service and return response
Unit Testing Controllers
Expected undefined to be [ Object({ name: 'recipename' }) ].
at Object.<anonymous> (test/controllersSpec.js:38:32)
at Object.invoke (node_modules/angular/angular.js:4839:19)
at Object.WorkFn (node_modules/angular-mocks/angular-mocks.js:3155:20)
EDIT
I decided to change the service to return a promise instead of a callback:
this.getAllRecipes = function () {
return $http.get('http://localhost:5000/api/recipes');
};
Then I changed the corresponding function in the controller:
vm.init = () => {
vm.hidden = true;
let allRecipes = dataService.getAllRecipes();
allRecipes.then(function(response) {
vm.recipes = response.data;
vm.getCategories(response.data);
},httpErrors.display('HTTP Error'))
.catch(errors.catch());
}
but I'm still getting
Expected undefined to be [ Object({ name: 'recipename' }) ].
Am I not implementing the promise correctly? Is there still something in my test that I'm missing?
You are currently mixing callbacks and promises.
The method getAllRecipes in the real service implementation takes a callback as an argument and executes it when the internal ajax call is done. The consumer of the method has no idea that the implementation uses promises internally.
The mock implementation of getAllRecipes however does not take or use a callback function but instead returns a promise.
You have in your controller:
dataService.getAllRecipes(function(response) {
vm.recipes = response.data;
vm.getCategories(response.data);
});
But with the mock implementation you would need:
dataService.getAllRecipes(function(response) {
vm.recipes = response.data;
vm.getCategories(response.data);
}).then(function (response) {
// Code
});
With your current implementation of getAllRecipes your mock could look like this:
getAllRecipesMock = {
getAllRecipes: function(callback) {
var response = {
data: [{
name: "recipename"
}]
};
callback(response);
}
};
Also note that unless you want to compare for reference equality, use toEqual instead of toBe:
expect(controller.recipes).toEqual([{
name: "recipename"
}]);
Demo: http://plnkr.co/edit/5BQBt4tTxohXEN0Drq3f?p=preview
An alternative is to change the service implementation to return a promise instead of using callbacks.

Are chrome notifications received via service workers batched or real time?

I am trying to implement Browser Push Notification for my website. I am noticing even though the browser received notification, it doesn't display the notification sometimes.
var showNotification = function (event, data) {
var notificationData = data['data'];
var title = notificationData['title'];
var body = notificationData['body'];
var icon = notificationData['icon'];
var notificationActionsData = notificationData["actions"];
var actions = [];
if(notificationActionsData) {
for(var i=0; i < notificationActionsData.length; i++) {
var action = {
action: "action" + i,
title: notificationActionsData[i].title,
};
actions.push(action);
}
}
var campaignId = notificationData["id"];
self.registration.showNotification(title, {
body: body,
icon: icon,
data: notificationData,
tag: notificationData.id,
actions: actions
});
pushowlReporting.tickle(campaignId, "delivery");
};
function processNotification(event) {
if (event.data) {
var data = event.data.json();
showNotification(event, data);
}
else {
fetch("https://" + hostname + "/api/v1/subdomain/" + subdomain + "/campaign/", {'mode': 'no-cors'}).then(
function (response) {
if (response.status !== 200) {
console.log('Looks like there was a problem. Status Code: ', response.status);
return;
}
// Examine the text in the response
response.text().then(function (responseText) {
var data = JSON.parse(responseText);
showNotification(event, data);
});
}
).catch(function (err) {
console.log('Fetch Error :', err);
}
);
}
}
self.addEventListener('push', function (event) {
event.waitUntil(processNotification(event));
});
My reporting API shows that the notification has been delivered however the browser displays the notification intermittently.
The notification display is quite erratic. Sometimes the notifications will display immediately, while sometimes it doesn't display for a while and all of a sudden all past notifications come in a batch. And at times some notifications don't get displayed at all.
Let me know if am doing something wrong here?
Function passed to event.waituntil should return a promise. If not the scope would be messed up as the lifetime of the event wouldnt have got extended.
https://developer.mozilla.org/en-US/docs/Web/API/ExtendableEvent/waitUntil
var showNotification = function (event, data) {
var notificationData = data['data'];
var title = notificationData['title'];
var body = notificationData['body'];
var icon = notificationData['icon'];
var notificationActionsData = notificationData["actions"];
var actions = [];
if(notificationActionsData) {
for(var i=0; i < notificationActionsData.length; i++) {
var action = {
action: "action" + i,
title: notificationActionsData[i].title,
};
actions.push(action);
}
}
var campaignId = notificationData["id"];
return self.registration.showNotification(title, {
body: body,
icon: icon,
data: notificationData,
tag: notificationData.id,
actions: actions
}).then(function (succ) {
pushowlReporting.tickle(campaignId, "delivery");
});
};
function processNotification(event) {
if (event.data) {
var data = event.data.json();
return showNotification(event, data);
}
else {
return fetch("https://" + hostname + "/api/v1/subdomain/" + subdomain + "/campaign/", {'mode': 'no-cors'}).then(
function (response) {
if (response.status !== 200) {
console.log('Looks like there was a problem. Status Code: ', response.status);
return;
}
// Examine the text in the response
response.text().then(function (responseText) {
var data = JSON.parse(responseText);
showNotification(event, data);
});
}
).catch(function (err) {
console.log('Fetch Error :', err);
}
);
}
}
I have just added return statements to your code. Try this out.

How test Service working with IndexedDB in AngularJS

I have app in AngularJS, where I make services, which stores data to IndexedDb.
It's look like this:
var IndexedDbServices = angular.module('IndexedDbServices', []);
IndexedDbServices.factory('IndexedDb', ['$window', '$q', function($window, $q){
var indexedDB = $window.indexedDB;
var db=null;
var open = function() {
var deferred = $q.defer();
var version = 3;
var request = indexedDB.open("lCApp", version);
request.onupgradeneeded = function(e) {
db = e.target.result;
e.target.transaction.onerror = indexedDB.onerror;
if(db.objectStoreNames.contains("collections")) {
db.deleteObjectStore("collections");
}
var store = db.createObjectStore("collections", {
keyPath: "id", autoIncrement : true
});
store.createIndex("name", "name", { unique: true });
store.createIndex("description", "description", { unique: false });
store.transaction.oncomplete = function(event) {
var customerObjectStore = db.transaction("collections", "readwrite").objectStore("collections");
customerObjectStore.add({name: "coll1", description: "desc for coll1"});
customerObjectStore.add({name: "coll2", description: "desc for coll2"});
};
};
request.onsuccess = function(e) {
db = e.target.result;
deferred.resolve();
};
request.onerror = function(){
deferred.reject();
};
return deferred.promise;
};
var findAll = function() {
var deferred = $q.defer();
if(db === null || db === undefined) {
deferred.reject("IndexDB is not opened yet!");
} else{
var trans = db.transaction(["collections"], "readwrite");
var store = trans.objectStore("collections");
var data = [];
// Get everything in the store;
var keyRange = IDBKeyRange.lowerBound(0);
var cursorRequest = store.openCursor(keyRange);
cursorRequest.onsuccess = function(e) {
var result = e.target.result;
if(result === null || result === undefined)
{
deferred.resolve(data);
}
else{
data.push(result.value);
result.continue();
}
};
cursorRequest.onerror = function(e){
console.log(e.value);
deferred.reject("Something went wrong!!!");
};
}
return deferred.promise;
};
return {
open: open,
add: add,
findAll: findAll
};
}]);
And I want test this code using unit test (jasmine). So i wrote this:
describe('IndexedDB service', function() {
beforeEach(function() {
module('IndexedDbServices');
});
it('should open db and find 2 collections', inject(function(IndexedDb) {
IndexedDb.open().then(function(e){
console.log(e);
}, function(err){
$window.alert(err);
});
console.log(IndexedDb.findAll());
}));
});
Would you advise me how test if function open in IndexedDb service create IndexedDb and add rows. And next I function open in IndexedDB service return all that records?
I don't know why, but in this test db is not created console.log(IndexedDb.findAll()); print: Promise{$$state: Object{status: 2, value: 'IndexDB is not opened yet!'}}
So Db is not created.
And next how use expect(..).toEqual() or something this in returned promises?
Let's have the service:
/*global window: false */
'use strict';
angular.module('main')
.config(['$provide', function ($provide) {
$provide.constant('indexedDB', window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB);
}])
.service('idb', function idbService($q, $rootScope, indexedDB) {
var service = this;
var db;
service.open = function () {
console.log('idb.open');
var deferred = $q.defer();
var request = indexedDB.open('mydb', 1);
request.onupgradeneeded = function (e) {
console.log('idb.open onupgradeneeded');
db = e.target.result;
if (!db.objectStoreNames.contains('mystore')) {
db.createObjectStore('mystore', {
keyPath: 'id'
});
}
};
request.onsuccess = function (e) {
console.log('idb.open onsuccess');
db = e.target.result;
deferred.resolve();
$rootScope.$apply(); // Propagate promise resolution to 'then' functions using $apply().
};
request.onerror = function (e) {
console.log('idb.open onerror ', e);
deferred.reject();
};
return deferred.promise;
};
service.put = function (key, value) {
console.log('idb.put(' + key + ', ' + value + ')');
var deferred = $q.defer();
var store = db.transaction(['mystore'], 'readwrite').objectStore('mystore');
var request = store.put({
id: key,
data: value
});
request.onsuccess = function () {
console.log('idb.put onsuccess');
deferred.resolve();
$rootScope.$apply(); // Propagate promise resolution to 'then' functions using $apply().
};
request.onerror = function (e) {
console.log('idb.put onerror ', e);
deferred.reject(e);
};
return deferred.promise;
};
service.get = function (key) {
console.log('idb.get' + '(' + key + ')');
var deferred = $q.defer();
var store = db.transaction(['mystore'], 'readwrite').objectStore('mystore');
var request = store.get(key);
request.onsuccess = function (e) {
console.log('idb.get onsuccess ', e.target.result);
deferred.resolve(e.target.result.data);
$rootScope.$apply(); // Propagate promise resolution to 'then' functions using $apply().
};
request.onerror = function (e) {
console.log('idb.get onerror', e);
deferred.reject(e);
};
return deferred.promise;
};
});
Test can be:
'use strict';
describe('idb', function () {
beforeEach(module('main'));
var idb;
var idbOpened;
beforeEach(angular.mock.inject(function (_idb_) {
idb = _idb_;
}));
beforeEach(function (done) {
idbOpened = false;
console.log(1);
idb.open().then(function () {
console.log(3);
idbOpened = true;
done();
})
console.log(2);
});
it('opens', function () {
expect(idbOpened).toBe(true);
console.log(4);
});
it('gets the put', function (done) {
console.log(10);
idb.put('666', 'bob').then(function () {
console.log(12);
idb.get('666').then(function (value) {
console.log(13);
expect(value).toBe('bob');
done();
console.log(14);
})
})
console.log(11);
});
});
Test output would be then:
LOG: 1
LOG: 'idb.open'
LOG: 2
LOG: 'idb.open onsuccess'
LOG: 3
LOG: 4
LOG: 1
LOG: 'idb.open'
LOG: 2
LOG: 'idb.open onsuccess'
LOG: 3
LOG: 10
LOG: 'idb.put(666, bob)'
LOG: 11
LOG: 'idb.put onsuccess'
LOG: 12
LOG: 'idb.get(666)'
LOG: 'idb.get onsuccess ', Object{id: '666', data: 'bob'}
LOG: 13
LOG: 14
Ugly stuff is a need to call
$rootScope.$apply();
to propagate promise resolution to 'then' functions in the test, because
it is not needed for the service itself.

Rewrite event emitter with Reactive programming(Semaphore example)

I'm use event emitters as synchronization primitives. For example I have one class which asks semaphore like structure in Redis. If semaphore is set it emits an event. The code is listed bellow:
var redis = require("redis"),
async = require('async'),
client = redis.createClient(),
assert = require('assert'),
EventEmitter = require('events').EventEmitter;
util = require('util');
var isMaster = false,
SEMAPHORE_ADDRESS = 'semaphore';
var SemaphoreAsker = function() {
var self = this;
var lifeCycle = function (next) {
client.set([SEMAPHORE_ADDRESS, true, 'NX', 'EX', 5], function(err, val) {
console.log('client');
if(err !== null) { throw err; }
if(val === 'OK') {
self.emit('crown');
} else {
console.log('still a minion');
}
});
};
async.forever(
function(next) {
setTimeout(
lifeCycle.bind(null, next),
1000
);
}
);
};
util.inherits(SemaphoreAsker, EventEmitter);
(new SemaphoreAsker()).on('crown', function() {
console.log('I`m master');
});
It works but looks a little bit heavy. Is it possible to rewrite the example with BaconJS(RxJS/whateverRPlibrary)?
The following should work in RXJS:
var callback = Rx.Observable.fromNodeCallback(client.set, client);
var source = Rx.Observable.interval(1000)
.selectMany(function() {
return callback([SEMAPHORE_ADDRESS, true, 'NX', 'EX', 5]);
})
.filter(function(x) { return x === 'OK'; })
.take(1);
source.subscribe(function(x) {
console.log("I am master");
});
If you are willing to additionally include the rx-node module you can also keep your event emitter structure by using
var emitter = RxNode.toEventEmitter(source, 'crown');
emitter.on('crown', function(){});
emitter.on('error', function(){});
emitter.on('end', function(){});
I used the basic Bacon.fromBinder to create a custom stream for this. Without a working example this is a bit of guesswork, but hopefully this helps you.
var redis = require("redis"),
client = redis.createClient(),
assert = require('assert'),
Bacon = require('bacon');
var SEMAPHORE_ADDRESS = 'semaphore';
var SemaphoreAsker = function() {
return Bacon.fromBinder(function (sink) {
var intervalId = setInterval(pollRedis, 1000)
return function unsubscribe() {
clearInterval(intervalId)
}
function pollRedis() {
client.set([SEMAPHORE_ADDRESS, true, 'NX', 'EX', 5], function(err, val) {
if(err !== null) { sink(new Bacon.Error(err)) }
else if(val === 'OK') { sink(new Bacon.Next('crown'))
else { assert.fail(); }
}
}
})
}
SemaphoreAsker().take(1).onValue(function() {
console.log("I am master")
})
The #paulpdanies answer but rewritten with Bacon:
var source = Bacon.interval(1000).flatMap(function() {
return Bacon.fromNodeCallback(
client, 'set', [SEMAPHORE_ADDRESS, true, 'NX', 'EX', 1]
);
})
.filter(function(x) { return x === 'OK'; })
.take(1);
source.onValue(function(x) {
console.log(x);
});

from a service, turning one function into two different functions

I have a function inside a service which has lots of lines and I want to convert that function into two different functions
this is the function
angular.module('capilleira.clickAndGambleMobile.services')
.factory('SportsFactory', function($http, $q, AuthFactory, LocalForageFactory, LeaguesFactory, CONSTANT_VARS) {
return {
getSports: function(customer) {
var defer = $q.defer(),
_this = this;
LocalForageFactory.retrieve(CONSTANT_VARS.LOCALFORAGE_SPORTS)
.then(function(sports) {
if (!_.isNull(sports)) {
defer.resolve(sports);
}else {
$http.get(CONSTANT_VARS.BACKEND_URL + '/lines/sports/' + customer.agent)
.success(function(sports) {
sports = _.sortBy(sports, function(sport) {
return sport.priority;
});
//THIS THE PART THAT I WANT TO MOVE FROM HERE
_this.getSportChecked(customer).then(function(sportChecked) {
var sportIds = _.pluck(sports, 'id'),
intersectedSports = _.intersection(sportIds, sportChecked.sport);
if (sports.length) {
sports = _.map(sports, function(sport) {
sport.checked = !_.includes(intersectedSports, sport.id);
return sport;
});
}else {
AuthFactory.logout();
}
});
LocalForageFactory.set(CONSTANT_VARS.LOCALFORAGE_SPORTS, sports);
defer.resolve(sports);
})
.error(function(err) {
defer.reject(err);
});
}
});
return defer.promise;
}
});
and here is what I have so far but I am receiving an error sports is not defined
getSports: function(customer) {
var defer = $q.defer(),
_this = this;
LocalForageFactory.retrieve(CONSTANT_VARS.LOCALFORAGE_SPORTS)
.then(function(sports) {
if (!_.isNull(sports)) {
defer.resolve(sports);
}else {
$http.get(CONSTANT_VARS.BACKEND_URL + '/lines/sports/' + customer.agent)
.success(function(sports) {
sports = _.sortBy(sports, function(sport) {
return sport.priority;
});
// HERE I AM CALLING THE NEW FUNCTION
_this.intersectedSportsChecked(customer);
LocalForageFactory.set(CONSTANT_VARS.LOCALFORAGE_SPORTS, sports);
defer.resolve(sports);
})
.error(function(err) {
defer.reject(err);
});
}
});
return defer.promise;
},
// HERE IS THE NEW FUNCTION
// UPDATED
intersectedSportsChecked: function(customer) {
var _this = this,
defer = $q.defer(),
rejection = function(err) {
defer.reject(err);
};
_this.getSports(customer).then(function(sports) {
_this.getSportChecked(customer).then(function(sportChecked) {
var sportIds = _.pluck(sports, 'id'),
intersectedSports = _.intersection(sportIds, sportChecked.sport);
if (sports.length) {
sports = _.map(sports, function(sport) {
sport.checked = !_.includes(intersectedSports, sport.id);
return sport;
});
}else {
AuthFactory.logout();
}
});
}, rejection);
},
so, what am I missing here ?

Categories

Resources