This is my code:
$scope.updatePosts = function() {
Posts.getIdsFromServer('http://localhost/postIds')
.then(function(ids) {
_.each(ids, function(id) {
Posts.getByIdFromDb(id)
.then(function(p) {
if(p) {
if(p.enabled) {
Posts.getFromServer('http://localhost/post/' + id)
.then(function(post) {
Posts.update(post);
})
}
} else {
Posts.getFromServer('http://localhost/post/' + id)
.then(function(post) {
Posts.insert(post);
})
}
});
});
}, function(error) {
console.log(error);
})
};
This code breaks because of _.each
I searched SO and found this:
function processCoolStuff(coolStuffs) {
return $q.all(_.map(coolStuffs, makeStuffCooler));
}
processCoolStuff(…).then(showAllMyCoolStuff);
But I cannot make it work, becasue I have too many async functions.
And I can get like 10000 posts and 10000 http calls, if I can use above method, will it consume a lot of memory?
How to solve it?
I never had such a problem, but instead of _.each, use angular.forEach
angular.forEach(ids, function(id, index, list) {}
Related
my question is pretty simple, i want to assign data in run time and get them again in vue instance
data() {
return {
panels:[],
};
},
created() {
this.fetchPanels();
//console.log(this) , i can find panels already assigned in this instance
//console.log(this.panels) , it gives me zero array
},
methods: {
fetchPanels() {
this.$http
.get(Shared.siteUrl+"/api/" + this.category_title + "/panels")
.then(function(response) {
this.panels = response.body.data;
});
},
If you're going to use async/await (and I agree you should), you should do so for the http call as well. await somefunc().then() feels like bad mixing of styles. This has the advantage of also being shorter.
data() {
return {
panels:[],
};
},
async created() {
await this.fetchPanels();
console.log(this.panels);
},
methods: {
async fetchPanels() {
const response = await this.$http.get(Shared.siteUrl + "/api/" + this.category_title + "/panels")
this.panels = response.body.data;
},
Keep in mind that the Vue lifecycle does not wait on your async lifecycle hooks. This won't be a problem in this example, but it's definitely good to keep in mind. I.e., if you added
mounted() {
console.log(this.panels);
},
it would come up empty, because the async tasks in created() will now happen after mounted()
Your console.log(this.panels) will be called before the async request.
Also, Use arrow function instead.
data() {
return {
panels:[],
};
},
created() {
this.fetchPanels();
//console.log(this) , i can find panels already assigned in this instance
//console.log(this.panels) , don't use this here
},
methods: {
fetchPanels() {
this.$http
.get(Shared.siteUrl+"/api/" + this.category_title + "/panels")
.then((response) => {
this.panels = response.body.data;
console.log(this.panels);
});
}
As developers suggested that, vue-resouce uses promise async tasks and to wait untill it gives its data
data() {
return {
panels:[],
};
},
async created() {
await this.fetchPanels();
console.log(this.panels)
},
methods: {
fetchPanels:async function() {
await this.$http
.get(Shared.siteUrl+"/api/" + this.category_title + "/panels")
.then((response) => {
this.panels = response.body.data;
});
}
I am trying to have a service return a promise, but keep getting PushService.initPush.then is not a function
Here is my service:
app.service('PushService', function($log, $q, $ionicPopup) {
return {
initPush: function() {
var deferred = $q.defer();
MFPPush.initialize (
function(successResponse) {
console.log("Successfully intialized push: " + successResponse);
deferred.resolve();
},
function(failureResponse) {
console.log("Failed to init push: " + JSON.stringify(failureResponse));
deferred.resolve();
}
)
return deferred;
}
}
}
And my controller:
PushService.initPush.then(function(response) {
console.log(response);
})
But am getting PushService.initPush.then is not a function why does this keep happening, to me it looks like I am returning a promise? I have been following this tutorial http://chariotsolutions.com/blog/post/angularjs-corner-using-promises-q-handle-asynchronous-calls/ and looked at this SO question Processing $http response in service but cant get it to work.
Thanks for the help
First, you need to call initPush method, not just access its property.
Second, in $q there's a not-so-subtle difference between deferred and promise APIs: the former is about modifying its state, and the second is about deciding what to do when it's settled (resolved or rejected). So you actually need to return deferred.promise (instead of deferred).
Finally, I'd recommend using $q constructor pattern instead, like shown in the doc:
initPush: function() {
return $q(function(resolve, reject) {
MFPPush.initialize(
function(successResponse) {
console.log("Successfully intialized push: " + successResponse);
resolve(successResponse);
},
function(failureResponse) {
console.log("Failed to init push: " + JSON.stringify(failureResponse));
reject(failureResponse);
}
);
});
}
As a matter of fact, if you don't need logging here, you can write it out as simple as ...
return $q(function(resolve, reject) {
MFPPush.initialize(resolve, reject);
});
Given the code below, how can I pass id to the applySaveAsync function?
var then = _.curry(function (f, thenable) {
return thenable.then(f);
});
var validateAsync = _.flow(
function () { return _(someCondition).showError(ERROR_01).value(); },
then(function () { return _(anotherCondition).showError(ERROR_02).value(); })
);
var save = _.flow(
validateAsync,
then(applySaveAsync),
then(saveCompleted)
);
function applySaveAsync(id) {
// Saving...
}
save(22); // Calling save function with some id.
I can get the id on the validateAsync function, but I cannot return it back since validateAsync should return a promise.
Any way to achieve that?
The simplest choice would be not to use _.flow for the definition of validateAsync.
Since validateAsync does not take parameters nor has a result, you should just change the definition of save to not use _.flow:
function save(id) {
return validateAsync()
.then(function(){ return applySaveAsync(id) })
.then(saveCompleted)
}
We could also change validateAsync to pass through the id:
function validateAsync(id) {
return _(someCondition).showError(ERROR_01).value()
.then(function () { return _(anotherCondition).showError(ERROR_02).value(); })
.then(_.constant(id));
}
and even do that while still using _.flow
var validateAsync = _.flow(
function(id) { return _(someCondition).showError(ERROR_01).value().then(_.constant(id)); },
then(function(id) { return _(anotherCondition).showError(ERROR_02).value().then(_.constant(id)); })
);
but I would advise against that since validateAsync is not supposed to be a function that does takes parameters.
Let's write a wrapper function for such instead to let us do the pass-around in a functional way:
function pass(fn) {
return function(id) {
return fn().then(function() {
return id;
});
}
}
(if you prefer, you can try to compose that from then, _.constant and more)
so that one can write
var save = _.flow(
wrap(validateAsync),
then(applySaveAsync),
then(saveCompleted)
);
I found this package useful for you. In Async cases, you can use this package.
Although flow is one of the best implementations for declarative programming, it doesn't support modern JS programming style.
import { Conductor } from '#puzzleio/conductor';
const conductor = Conductor.createDefault();
const myAsyncWorkflow = conductor
.add(validateAsync)
.if({
check: item => item.isValid === true,
handler: item => console.log('Item is valid')
},
{
// else block
handler: item => console.log('Validation failed')
});
myAsyncWorkflow.run(obj)
.then(() => console.log('Successfully validated'))
.catch(console.error);
So i brought to life this abomination and i couldnt for the life of me get my head around how to optimise it in such a way i can run this chain properly using Promise.all / Promise.join.
Anyone able to point me in the right direction? Should probably separate the methods first.
Any insight is appreciated.
getOpenIDConf: function() {
return client
.getAsync('openId')
.then(
function(result) {
if (!result) {
return request
.getAsync({
url: 'https://accounts.google.com/.well-known/openid-configuration',
json: true
}).spread(
function(response, body) {
var result = JSON
.stringify(body);
client.setAsync('openId',
result).then(
function() {
return result;
});
});
} else {
return result;
}
});
},
[EDIT] To clarify, i'm using bluebird
Refactoring a bit and changing the code style gives this.
getOpenIDConf: () => client.getAsync('openId').then(result =>
result || request.getAsync({
url: 'https://accounts.google.com/.well-known/openid-configuration',
json: true
}).get(1).then(JSON.stringify).then(result =>
client.setAsync('openId', result).return(result);
)
)
},
A few features of a good promise library (not sure which one you are using) is that you can chain the promises like so:
doSomething(function(result) {
return doSomethingElse();
}).then(function(result2) {
return doSomethingElseAgain();
}).then(function(result3) {
// It all worked!
}).catch(function() {
// Something went wrong
});
Or you can wait for a set of them to complete:
var promiseArray = [];
promiseArray.push(doSomething());
promiseArray.push(doSomethingElse());
promiseArray.push(doSomethingElseAgain());
Promise.all(promiseArray).then(function() {
// It all worked!
}).catch(function() {
// Something went wrong
});
Hope this is informative.
I'm attempting to test a custom filter I've built. The issue I'm running into is that this filter relies on an asynchronous call through a service. Below is my relevant filter code first, then my current test:
.filter('formatValue', ['serverService', '_', function(serverService, _) {
var available = null;
var serviceInvoked = false;
function formatValue(value, code) {
var details = _.findWhere(available, {code: code});
if (details) {
return details.unitSymbol + parts.join('.');
} else {
return value;
}
}
getAvailable.$stateful = true;
function getAvailable(value, code) {
if (available === null) {
if (!serviceInvoked) {
serviceInvoked = true;
serverService.getAvailable().$promise.then(function(data) {
available = data;
});
}
} else {
return formatValue(value, code);
}
}
return getAvailable;
}])
test:
describe('filters', function() {
beforeEach(function() {
module('underscore');
module('gameApp.filters');
});
beforeEach(module(function($provide) {
$provide.factory('serverService', function() {
var getAvailable = function() {
return {
// mock object here
};
};
return {
getAvailable: getAvailable
};
});
}));
describe('formatValue', function() {
it('should format values', inject(function(formatValueFilter) {
expect(formatValueFilter(1000, 'ABC')).toEqual('å1000');
}));
});
});
The error I'm encountering when running my tests is:
TypeError: 'undefined' is not an object (evaluating 'serverService.getAvailable().$promise.then')
Your mock service needs to return a resolved promise. You can do this by injecting $q and returning $q.when(data)
However, I would think about refactoring this filter first. Filters are intended to be fast computations and probably should not be dependent on an asynchronous call. I would suggest moving your http call to a controller, then pass in the data needed to the filter.