Dexie toArray() Promise - promise

I need to create and consume an array from Dexie ordeBy Promise
var list = [];
const ms = wmsLocalDb.table1.orderBy("index").toArray();
ms.each(m => list.push(m)).then(
//When list is complete I want to consume
for (var i = 0; i < list.length; i++) {
//something
}
);
But i cannot read list array.
Best regards
Ingd

You want something along the following lines :
wmsLocalDb.table1.orderBy("index").toArray()
.then(list => {
list.forEach(item => {
//something
});
})
.catch(error => {
// handle error
});

Related

channel.on not recognized as a function in Twilio API

I have the following function in a ReactJS app that is supposed to initialize the Twilio services that I am using. However, it seems like the Twilio channels are not being accessed correctly. Here is my code:
componentDidMount() {
let chatClient = this;
$.ajax({
method: "GET",
url: 'get_twilio_token',
data: {device: chatClient.device},
success: (data) => {
let accessManager = new Twilio.AccessManager(data.token);
//let messagingClient = new Twilio.Chat.Client(data.token);
let messagingClient = new Twilio.Chat.Client.create(data.token).then(client => {
client.getUserChannelDescriptors().then(channels => {
let channelsHash = {};
console.log('inside callback of messagingClient2')
channels.items.map(channel => {
channel.on('messageAdded', () => {})
channelsHash[channel.uniqueName] = channel;
});
});
});
}
});
}
This function throws an error message saying TypeError: channel.on is not a function in the line channel.on('messageAdded', () => {}).
Any help is appreciated. Thanks.
getUserChannelDescriptors() returns ChannelDescriptors not Channels. To get Channel you have to call getChannel for the descriptor: https://media.twiliocdn.com/sdk/js/chat/releases/1.0.0/docs/ChannelDescriptor.html#getChannel__anchor
This is how I've done it
async function getChannels() {
// Initialize the chat client
this.chatClient = new Chat(this.state.twilioToken);
await this.chatClient.initialize();
// Get channel descriptors
this.chatClient.getUserChannelDescriptors().then(paginator => {
let channels = [];
let channelsBulkFetch = [];
if (paginator.items.length) {
channels = paginator.items;
// Loop through all channels and call getChannel() for each cahnnel
for (let i = 0; i < paginator.items.length; i++) {
channelsBulkFetch.push(channels[i].getChannel());
}
// Loop through each channel detailed object and perform various operations
channels.map(channel => {
// Do whatever you want with channel object
channel.on('messageAdded', this.messageAdded);
});
}
})
}
And for sorted channels with respective to last message timestamp
async function getSortedChannels() {
// Initialize the chat client
this.chatClient = new Chat(this.state.twilioToken);
await this.chatClient.initialize();
// Get channel descriptors
this.chatClient.getUserChannelDescriptors().then(paginator => {
let channels = [];
let sortedChannels = [];
let channelsBulkFetch = [];
if (paginator.items.length) {
channels = paginator.items;
// Loop through all channels and call getChannel() for each cahnnel
for (let i = 0; i < paginator.items.length; i++) {
channelsBulkFetch.push(channels[i].getChannel());
}
/**
* Additional part for sorting
*/
sortedChannels = channels.sort(function (a, b) {
// Turn strings into dates, and then subtract them
// If channel doesn't have any message consider the dateDreated for sorting
return new Date(b.lastMessage ? b.lastMessage.timestamp : b.dateCreated) - new Date(a.lastMessage ? a.lastMessage.timestamp : a.dateCreated);
});
// Loop through each channel detailed object and perform various operations
sortedChannels.map(channel => {
// Do whatever you want with channel object
channel.on('messageAdded', this.messageAdded);
});
}
})
}

Promise for-loop with Ajax requests

I'm creating a native JavaScript application which does loads of Ajax calls in the same process at a certain time. Instead of going through a normal for loop and do them all at once, I thought I'd wait for the Ajax call to complete and then do the next one.
With the help of Stackoverflow I've managed to do this like the following:
function ajaxCall(index) {
return new Promise(function(resolve) {
// Ajax request {
resolve();
// }
});
}
Promise.resolve(0).then(function loop(i) {
if (i < length) {
return ajaxCall(i).thenReturn(i + 1).then(loop);
}
}).then(function() {
// for loop complete
});
Promise.prototype.thenReturn = function(value) {
return this.then(function() {
return value;
});
};
However, this is too slow for me. I want to be able to keep a var which keeps track of how many Ajax calls are currently in the process so that I can limit the amount.
I've tried multiple things, but I keep running into ininite loops or not getting to the desired result.
How can I do multiple, limited by a specific number, async Ajax calls using the Promise for loop?
Sounds like you want a version of Promise.all that takes an array of asynchronous functions rather than promises, and a ceiling on the number of simultaneous operations. Something like:
Promise.allFuncs = (funcs, n) => {
n = Math.min(n, funcs.length);
var results = [];
var doFunc = i => funcs[i]().then(result => {
results[i] = result; // store result at the correct offset
if (n < funcs.length) {
return doFunc(n++);
}
});
// start only n simultaneous chains
return Promise.all(funcs.slice(0, n).map((p, i) => doFunc(i)))
.then(() => results); // final result
};
// --- Example: ---
var log = msg => div.innerHTML += msg + "<br>";
var wait = ms => new Promise(resolve => setTimeout(resolve, ms));
var example = ['a','b','c','d','e','f'].map(name =>
() => (log("started "+name),wait(2000).then(() => (log("ended "+ name), name))));
Promise.allFuncs(example, 2)
.then(results => log("Results: "+ results))
.catch(log);
<div id="div"></div>

Get Specific Data From ngStorage

I have a bunch of data on JSON using LocalStorage from ng-storage like this,
[Object { judul="Just", isi="Testing"}, Object { judul="To", isi="Get"}, Object { judul="Specific", isi="Data"}]
but I want to get one specific data to get the "isi" value, how to do that ?
You can do this by adding a get function to your factory
for example :
.factory ('StorageService', function ($localStorage) {
$localStorage = $localStorage.$default({
things: []
});
var _getAll = function () {
return $localStorage.things;
};
//-----
var _get = function (isi) {
for( var i = 0; i < $localStorage.things.length ; i++ ){
if( $localStorage.things[i].isi === isi ){
return $localStorage.things[i];
}
}
}
return {
getAll: _getAll,
get : _get
};
})
and in your controller you can get the specific data by passing the id of your object
var objectInlocal = StorageService.get(Thing.isi);

Get Data from parse.com Promises

I am trying to use parse.com promises to retrieve job data as well as user relation data associated with the job. I have a function that returns promises but not job data. How do I get the job & employee information from the returned promises?
Logically I want to:
1) Query Parse to get array of jobs
2) For each job, query Parse again to get the employee relation information
3) Create local object that contains job & employee details
4) Add each job object to local array
5) Load table with array of objects once all information has been retrieved from Parse
I can do steps 1-4 but I can't figure out how to wait until all information has been retrieved from Parse to refresh the local table.
function getJobPromises (){
var promises = [];
var Job = Parse.Object.extend("Job");
var query = new Parse.Query(Job);
query.equalTo("company", company);
query.notEqualTo("isDeleted", true);
query.limit(1000); // raise limit to max amount
query.find().then(function(results) {
// Create a trivial resolved promise as a base case.
var promise = Parse.Promise.as();
_.each(results, function(result) {
// For each item, extend the promise with a function to add it to the job array
promise = promise.then(function() {
// Return a promise that will be resolved when the job details have been added to the array
var object = result;
promises.push(getEmployeeName(object));
allJobDataArray = promises;
});
});
return Parse.Promise.when(promises);
}).then(function() {
// Every job has been retrieved
console.log("All items have been returned. Refresh table...");
console.log(allJobDataArray);
});
}
The function that does the relational query to get the users associated with the job
function getEmployeeName(jobObject) {
var employeeNameArray = [];
//Query to get array of employees for the passed in job
var rQuery = jobObject.relation("employee");
return rQuery.query().find({
success: function(employees){
//Get employees full name for each job
for (var i = 0; i < employees.length; i++) {
var objEmployee = employees[i];
var fullName = objEmployee.get("fullName");
employeeNameArray.push(fullName);
console.log(employeeNameArray);
}
},
error: function(error){
response.error(error);
}
});
}
Update
It is now working thanks to #eduardo
I have a public array to hold the job objects.
var jobObjectsArray = [];
In the getEmployeeName function I am creating the job objects and adding them to that array
function getJobPromises (){
var promises = [];
var Job = Parse.Object.extend("Job");
var query = new Parse.Query(Job);
query.equalTo("company", company);
query.notEqualTo("isDeleted", true);
query.limit(1000); // raise limit to max amount
query.find().then(function(results) {
_.each(results, function(result) {
promises.push(getEmployeeName(result));
});
return Parse.Promise.when(promises);
}).then(function(allJobDataArray) {
// allJobDataArray should be actually an Array of Array
console.log(jobObjectsArray);
refreshTable();
});
}
function getEmployeeName(jobObject) {
var employeeNameArray = [];
//Query to get array of employees for the passed in job
var rQuery = jobObject.relation("employee");
return new Promise(
function(resolve, reject) {
rQuery.query().find({
success: function(employees){
//Get employees full name for each job
for (var i = 0; i < employees.length; i++) {
var objEmployee = employees[i];
var fullName = objEmployee.get("fullName");
employeeNameArray.push(fullName);
var objAllJobs = new Object();
objAllJobs["jobId"] = jobObject.id;
objAllJobs["location"] = jobObject.get("location");
objAllJobs["startTime"] = jobObject.get("startTime");
objAllJobs["employee"] = employeeNameArray;
jobObjectsArray.push(objAllJobs);
}
console.log(employeeNameArray);
resolve(employeeNameArray);
},
error: function(error){
reject(error);
}
});
}
);
There was a few incorrect uses of the promise concept. I will go through them, but first here is the final code:
function getJobPromises (){
var promises = [];
var Job = Parse.Object.extend("Job");
var query = new Parse.Query(Job);
query.equalTo("company", company);
query.notEqualTo("isDeleted", true);
query.limit(1000); // raise limit to max amount
query.find().then(function(results) {
_.each(results, function(result) {
promises.push(getEmployeeName(result));
});
return Parse.Promise.when(promises);
}).then(function(allJobDataArray) {
// allJobDataArray should be actually an Array of Array
console.dir(allJobDataArray);
console.log(allJobDataArray[0]);
});
}
function getEmployeeName(jobObject) {
var employeeNameArray = [];
//Query to get array of employees for the passed in job
var rQuery = jobObject.relation("employee");
return rQuery.query().find({
success: function(employees){
//Get employees full name for each job
for (var i = 0; i < employees.length; i++) {
var objEmployee = employees[i];
var fullName = objEmployee.get("fullName");
employeeNameArray.push(fullName);
}
console.log(employeeNameArray);
return employeeNameArray;
},
error: function(error){
response.error(error);
}
});
}
"Parse.Promise.as()" should be used only if you have a value that you want to return as a promise. Something like:
Parse.Promise.as("my value").then(function(foo) {
console.log(foo) // "my value"
});
So if your "getEmployeeName" function is returning a promise, which means that this "rQuery.query().find" returns a promise, you don't have to create a new promise or use the "Parse.Promise.as()", it is already a promise and you can push it to the promises array.
Another problem was that you were not return anything in the "getEmployeeName" method callback. Take a look into my version, I'm returning "employeeNameArray".
My version will only work if this "rQuery.query().find" method returns a promise. If that is not the case, you can create a new promise using its callbacks like this:
function getEmployeeName(jobObject) {
var employeeNameArray = [];
//Query to get array of employees for the passed in job
var rQuery = jobObject.relation("employee");
return new Promise(
function(resolve, reject) {
rQuery.query().find({
success: function(employees){
//Get employees full name for each job
for (var i = 0; i < employees.length; i++) {
var objEmployee = employees[i];
var fullName = objEmployee.get("fullName");
employeeNameArray.push(fullName);
}
console.log(employeeNameArray);
resolve(employeeNameArray);
},
error: function(error){
reject(error);
}
});
}
);
}
Please notice this "new Promise()" depends on the browser support of Promise, I don't know if Parse has an equivalent. Anyways you can use it with a polyfill that implements the necessary code if the browser has no support.
More about standard promises: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
Polyfill: https://github.com/jakearchibald/es6-promise/
Hope this helps.

Ajax call within a loop using $resource

I'm in difficulty doing this operation correctly.
I have an Order and for every item I have to get the data from the API, what I'm doing is this:
if ($scope.order.order_items.length > 0) {
var itemArray = [];
for (var i = 0; i < $scope.order.order_items.length; i++) {
var itemId = $scope.order.order_items[i].id;
Items.get({
itemId: itemId
}).$promise.then(function (data) {
itemArray.push(data.item);
});
}
$scope.order.order_items = itemArray;
}
The API receive the request and send the data back but the promise do not return anything...
One more error here is from jshint: Don't make functions within a loop.
It will be nice to solve both the issues for me... I tried to create an external function but having the same issue not returning data I don't know if I was doing it well, the external function I was doing is:
function addItem(id) {
Items.get({
itemId: id
}).$promise.then(function (data) {
console.log(data);
return data.item;
});
}
You are making an asynchronous call from the code and thinking that it will work like synchronously. As you are assigning itemArray to $scope.order.order_items outside the factory, at that time itemArray is blank. Before making that assignment you need to ensure that all the ajax call the each item has been completed or not. You could use $q.all for such scenario. $q.all need an promise array & it will call the .then function when all the promise gets resolved.
if ($scope.order.order_items.length > 0) {
var itemArray = [], promiseArray = [];
for (var i = 0; i < $scope.order.order_items.length; i++) {
var itemId = $scope.order.order_items[i].id;
var currentPromise = Items.get({
itemId: itemId
}).$promise.then(function (data) {
itemArray.push(data.item);
return true; //returning dummy value from promise.
});
promiseArray.push(currentPromise); //creating promise array
}
$q.all(promiseArray) //giving promise array input.
.then(function(data){ //success will call when all promises get resolved.
$scope.order.order_items = itemArray;
},function(error){
console.log("Error occured")
});
}
I would avoid reading and writing to the same array and instead use another array for the actual items.
As Resource returns an instance that gets filled on success you should be fine adding the instances to the scope directly. With that you reduce your code a lot and also remove the jshint warning.
if ($scope.order.order_items.length > 0) {
$scope.order.order_items_with_data = [];
for (var i = 0; i < $scope.order.order_items.length; i++) {
var itemId = $scope.order.order_items[i].id;
$scope.order.order_items_with_data.push(Items.get({itemId: itemId}));
}
}

Resources