How to synchronize the function commands in angular js - javascript

I am creating an ionic application and in particular scenario
when an employee is selected from a list(generated from a JSON data array), his detail is to be shown from here
var employees = [{"id": 325, "firstName": "James", "lastName":
"King", "managerId": 0, "managerName": "", "reports": 4, "title":
"President and CEO", "department": "Corporate", "cellPhone":
"617-000-0001", "officePhone": "781-000-0001", "email":
"jking#gmail.com", "city": "Boston, MA", "pic": "James_King.jpg",
"twitterId": "#fakejking", "blog": "http://coenraets.org"}.....
All i need is to find the index of ID to show the complete object.
findById: function(employeeId) {
var deferred = $q.defer();
var searchValue = {'id': employeeId };
index = -1;
_.each(employees, function(data, idx) {
if (_.isEqual(data, searchValue)) {
index = idx;
return;
}
});
var employee = employees[index];
deferred.resolve(employee);
return deferred.promise;
},
for that i am using this function which is not taking debugger inside the _.each function
kindly tell me where m i wrong.

It's not going to work because expression _.isEqual(employees[xxx], {id: 325}) will never return a match.
Instead use _.find method
findById: function(employeeId) {
var employee = _.find(employees, {id: employeeId});
return $q.when(employee);
}

I think you can simplify your function a little, because you are using lodash:
findById: funtion(employeeId) {
return _.findWhere(employees, {id : employeeId});
}
Futhermore I do not see any reason to use promises here, but to go with that notion, you could try this:
findById: funtion(employeeId) {
var deferred = $q.defer();
$timeout(function() {
var employee = _.findWhere(employees, {id : employeeId});
if (found !== undefined) {
deferred.resolve(employee);
} else {
deferred.reject();
}, 0);
return deferred.promise;
}
You need to return the promise deferred.promise before you resolve() or reject(), so you can wait for that in your callee.
Hope that helps!

I don't know if your really need the index. To work on a solution, which returns the employee at that moment, when you find the data, would be better and shorter. Than you should also jump out of the loop.
If your debugger is not jumping inside _.each maybe your employees array is empty.
You could try something like this:
findById: function(employeeId) {
var deferred = $q.defer();
// deferred should be inside the scope of _.each
// because it is defined here
var searchValue = {'id': employeeId };
//index = -1;
// check your data here
// for example console.log(employees.length)
// or make a breakpoint here and check employees
_.each(employees, function(data, idx) {
// make a console.log(idx) here to check your data
if (_.isEqual(data, searchValue)) {
deferred.resolve(data);
return deferred.promise;;
}
});
},

Related

Javascript Promises: Iterate over all object keys arrays and then resolve

I have this JS object:
let setOfWords = {
"nouns": [
"work",
"construction",
"industry"
],
"verbs": [
"work"
],
}
I'm using the google translate API which calls a REST resource, so I need to wait for the response of each translation and then resolve the same object structure but with the translated words.
function translateByCategory(){
let translatedObj = {};
return new Promise(function(resolve, reject){
Object.keys(obj).forEach(function(category){
if (translatedObj[category] == undefined) {
translatedObj[category] = [];
}
setOfWords.forEach(function(word){
google.translate(word, 'es', 'en').then(function(translation){
translatedObj[category].push(translation.translatedText);
});
});
// return the translatedObj until all of the categories are translated
resolve(translatedObj);
});
});
}
You can use Promise.all() to wait for all promise fulfillments (or first rejection):
var translateRequests = [];
Object.keys(setOfWords).forEach(function(category){
setOfWords[category].forEach(function(word){
translateRequests.push(google.translate(word, 'es', 'en'));
});
});
});
Promise.all(translateRequests).then(function(translateResults){
//do something with all the results
});
See the docs: Promise.all()
Individual promises need to be aggregated with Promise.all() and fundamentally, that's what's missing.
But you can do better by reducing the number of calls to the Google service.
The Google translate API allows multiple text strings to be translated in one hit by passing an array of words instead of one word per call, giving you a performance advantage though probably not price advantage - google currently charges for its translation service "per character", not "per call".
I can't find any documentation for google.translate() but, with a few assumptions, you may be able to write :
function translateByCategory(obj, sourceCode, targetCode) {
let translatedObj = {};
var promises = Object.keys(obj).map(function(key) {
return google.translate(obj[key], sourceCode, targetCode).then(function(translations) {
translatedObj[key] = translations.map(function(t) {
return t.translatedText || '-';
});
}, function(error) {
translatedObj[key] = [];
});
});
return Promise.all(promises).then(function() {
return translatedObj;
});
}
If that doesn't work, then this documentation explains how to call google's RESTful translation service directly.
You should be able to write :
function translateTexts(baseParams, arrayOfStrings) {
let queryString = baseParams.concat(arrayOfStrings.map(function(str) {
return 'q=' + encodeURIComponent(str);
})).join('&');
return http.ajax({ // some arbitrary HTTP lib that GETs by default.
url: 'https://translation.googleapis.com/language/translate/v2?' + queryString,
}).then(function(response) {
return response.data.translations.map(function(t) {
return t.translatedText || '-';
});
}, function(error) {
translatedObj[key] = []; // on error, default to empty array
});
}
function translateByCategory(obj, sourceCode, targetCode) {
let baseParams = [
'key=' + MY_API_KEY, // from some outer scope
'source=' + sourceCode, // eg 'en'
'target=' + targetCode // eg 'es'
];
let translatedObj = {};
let promises = Object.keys(obj).map(function(key) {
return translateTexts(baseParams, obj[key]).then(function(translations) {
translatedObj[key] = translations;
}, function(error) {
translatedObj[key] = []; // on error, default to empty array
});
});
return Promise.all(promises).then(function() {
return translatedObj;
});
}
In either case, call as follows :
let setOfWords = {
"nouns": [
"work",
"construction",
"industry"
],
"verbs": [
"work"
],
};
translateByCategory(setOfWords, 'en', 'es').then(function(setOfTranslatedWords) {
console.log(setOfTranslatedWords);
});
The method suggested by #hackerrdave can be modified to make it more compatible with async await feature of JavaScript, do this like the following:
function translateByCategory(){
return new Promise(function(resolve, reject){
var translateRequests = [];
Object.keys(setOfWords).forEach(function(category){
setOfWords[category].forEach(function(word){
translateRequests.push(google.translate(word, 'es', 'en'));
});
});
Promise.all(translateRequests).resolve(resolve(translateRequests));
});
}
So now you can do something like:
let translatedObj = await translateByCategory();
And you will get what you want in "translatedObj".

Best practice to get a json response object in angularjs

I have an API which return a json array object, right now, I get the json in my Controller like this and it works just fine :
angular.module('lyricsApp', [])
.controller('LyricsController', ['$scope', 'ApiCall', function ($scope, ApiCall) {
$scope.lyrics = {
id: "",
songName: "",
singerName: "",
writtenBy: "",
lyricText: "",
isEnable: "",
created_at: "",
updated_at: ""
};
$scope.searchLyric = function () {
var result = ApiCall.GetApiCall().success(function (lyrics) {
$scope.lyrics.id = lyrics.data.id
$scope.lyrics.singerName = lyrics.data.singerName;
$scope.lyrics.songName = lyrics.data.songName;
$scope.lyrics.writtenBy = lyrics.data.writtenBy;
$scope.lyrics.lyricText = lyrics.data.lyricText;
$scope.lyrics.isEnable = lyrics.data.isEnable;
$scope.lyrics.created_at = lyrics.data.created_at;
$scope.lyrics.updated_at = lyrics.data.updated_at;
});
}
}])
But I think this is not a good practice, I already try this :
var result = ApiCall.GetApiCall().success(function (lyrics) {
$scope.lyrics=lyrics.data;
});
in this case I get undefined value :
console.log($scope.lyrics.id); // show Undefined
So, if you guys can suggest a better way I will be appreciate it.
You are doing the right thing, except for console.log. If your log statement is executed before the assignment is done, you will get the undefined value.
Also I don't see why you would do a var result =
You can simply do
ApiCall.GetApiCall('v1', 'lyrics', '1').success(function (data) {
$scope.lyrics = data.data;
console.log($scope.lyrics.id);
}).error(fucntion(data){
console.log(data);
});

Search for a related json data

How can i find data that is related to the already known data?
( I'm a newb. )
For example here is my json :
[
{ "id": "1", "log": "1","pass": "1111" },
{ "id": 2, "log": "2","pass": "2222" },
{ "id": 3, "log": "3","pass": "3333" }
]
Now i know that "log" is 1 and i want to find out the data "pass" that is related to it.
i've tried to do it so :
The POST request comes with log and pass data , i search the .json file for the same log value and if there is the same data then i search for related pass
fs.readFile("file.json", "utf8", function (err, data) {
var jsonFileArr = [];
jsonFileArr = JSON.parse(data); // Parse .json objekts
var log = loginData.log; // The 'log' data that comes with POST request
/* Search through .json file for the same data*/
var gibtLog = jsonFileArr.some(function (obj) {
return obj.log == log;
});
if (gotLog) { // If there is the same 'log'
var pass = loginData.pass; // The 'pass' data that comes with POST request
var gotPass = jsonFileArr.some(function (obj) {
// How to change this part ?
return obj.pass == pass;
});
}
else
console.log("error");
});
The problem is that when i use
var gotPass = jsonFileArr.some(function (obj) {
return obj.pass == pass;
});
it searches through the whole .json file and not through only one objekt.
Your main problem is that .some() returns a boolean, whether any of the elements match your predicate or not, but not the element itself.
You want .find() (which will find and return the first element matching the predicate):
const myItem = myArray.find(item => item.log === "1"); // the first matching item
console.log(myItem.pass); // "1111"
Note that it is possible for .find() to not find anything, in which case it returns undefined.
The .some() method returns a boolean that just tells you whether there is at least one item in the array that matches the criteria, it doesn't return the matching item(s). Try .filter() instead:
var jsonFileArr = JSON.parse(data);
var log = loginData.log;
var matchingItems = jsonFileArr.filter(function (obj) {
return obj.log == log;
});
if (matchingItems.length > 0) { // Was at least 1 found?
var pass = matchingItems[0].pass; // The 'pass' data that comes with the first match
} else
console.log("error"); // no matches
Using ES6 Array#find is probably the easiest, but you could also do (among other things)
const x = [{
"id": "1",
"log": "1",
"pass": "1111"
}, {
"id": 2,
"log": "2",
"pass": "2222"
}, {
"id": 3,
"log": "3",
"pass": "3333"
}];
let myItem;
for (let item of x) {
if (item.log === '1') {
myItem = item;
break;
}
}
console.log(myItem);

Why I'm getting the var undefined

I'm trying to get a Rest array and then display it on my HTML.
the problem that I'm facing is that In My factory I'm able to get the array and display it's content, but not in my controller where I'm always getting the Undefined var. here is my Factory
.factory('coursesService', function($resource) {
var service = {};
service.getAllCouses = function (){
var Courses = $resource("/myproject/rest/training/trainings");
var data = Courses.query().$promise.then(function(data)
{
service.data= data;
console.log("ligne 1: ", service.data[0].name);
console.log("ligne 1: ", service.data[0].creator);
console.log("ligne 2: ", data[1].name);
console.log("ligne 2: ", data[1].creator);
return service.data;
});
}
return service;
})
and my controller
.controller("CoursesController",
function CoursesController($scope, coursesService) {
var courses = {};
courses = coursesService.getAllCouses();
console.log("courses: ", courses);
})
as results I'm getting this:
courses: undefined
ligne 1: Angular
ligne 1: Object {id: "1", username: "User1", email: "user1#gmail.com", password: "password", userProfile: Object}
ligne 2: JavaScript
ligne 2: Object {id: "1", username: "User1", email: "user1#gmail.com", password: "password", userProfile: Object}
Why I'm getting courses: undefined? and Shouldn't be displayed after the list that I'm displaying in the factory?
Your getAllCouses function never returns anything, and so calling it always results in undefined. The callback to the query promise then handler returns something, but not getAllCouses.
You'll need to have getAllCouses return the promise, and then use the result from within a then handler on that promise. You can't just use its return value directly, not if Courses.query() is async (and if it isn't, why is it returning a promise?).
That would look something like this:
.factory('coursesService', function($resource) {
var service = {};
service.getAllCouses = function (){
var Courses = $resource("/myproject/rest/training/trainings");
var data = Courses.query().$promise.then(function(data) {
service.data= data;
console.log("ligne 1: ", service.data[0].name);
console.log("ligne 1: ", service.data[0].creator);
console.log("ligne 2: ", data[1].name);
console.log("ligne 2: ", data[1].creator);
return service.data;
});
return data; // <=== Return the promise (`data` is a bit of a suspect name)
};
return service;
})
Then:
.controller("CoursesController", function CoursesController($scope, coursesService) {
coursesService.getAllCouses().then(function(courses) { // <=== Use the promise
console.log("courses: ", courses); // <===
}); // <===
})
...but I'm not an Angular guy.
getAllCouses() does not return a value, it just sets two local variables, Courses and data.
The Courses.query promise only resolves once the web request is complete, so those logs are delayed.
I fixed the issue by updating my service and controller like this:
.factory('coursesService', function($resource) {
return $resource("/myproject/rest/training/trainings", {
query : {
method : "GET",
isArray : true
}
});
});
I just added the
isArray : true
and i updated the controller
.controller(
"CoursesController",
function UserController($scope, coursesService) {
coursesService.query(function(data) {
console.info("data: ", data)
console.log("1st course: ", data[0].name)
$scope.Courses = data;
});
I fix it simply in this way:
.factory('coursesService', function($resource) {
return $resource("/myproject/rest/training/trainings")
})
and the controller:
.controller("coursesController", function($scope, coursesService) {
coursesService.query(function(data) {
$scope.Courses = data;
});
})

Parse Promise and Parse Relation toghether - Javascript API

Ok guys! Could someone help me?
I have a parse DB as follow:
Person(id, name)
Product(id,serial)
Invoice(id,<Relation>products, personId)
I need to build a function that returns an array of Objects,
in each Object person.name, invoice.id,invoice.products
I'm not so good with english so I wish you understand what i mean.
so i use Parse.Promise to query the "person" and the "invoice"
function Obj(name, invoiceId, products) {
return {
name: name || '',
invoiceId: invoiceId || '',
products: products || []
};
}
function retreiveData(aName) {
var retval = [],
personQuery = new Parse.Query("Person");
personQuery.equalTo('name', aName).first().then(function(person) {
var invoiceQuery = new Parse.Query("Invoice");
return invoiceQuery.equalTo('personId', person.id).query().find();
}), then(function(invoices) {
//until here everythinks work fine
// now i've the invoices list and i have to look for related products
var promise = new Parse.Promise();
_.each(invoices, function(invoice) {
var obj = new Obj(aName, invoice.id),
promise = new Parse.Promise();
invoice.relation('products').query().find().then(function(products) {
obj.products = products;
// here i expect to have the obj fulfilled with all data
retval.push(obj);
promise.resolve();
});
return promise;
});
return promise;
});
}
var aName = 'Paul';
retreiveData(aName).then(function(retval) {
console.log('success');
/* here i have to have somethin like
retval=[{
name='paul',
invoiceId='12412412',
products=[{prod1},{prod2},{prod3}]
},{
name='paul',
invoiceId='67413412',
products=[{prod5},{prod10},{prod33}]
}]
*/
});
any idea?
i know the inner promise is wrong, but i don't understand how to fix
Thanks guyz!

Categories

Resources