I have this part of code that work but strangely the latest step of outputting the result doesn't work.. When i try to log the first element of array it returns undefined bacause the execution is asynchronous. I thought to build a series of nested callbacks but I think that is a bad practice. Is there any other way to makes it work without create nested promise callbacks?
CODE:
var ImgGalleyURL = [];
//CONTROLLO SE SONO STATE INSERITE IMMAGINI DA CARICARE E LE CARICO
if (postwp.postImgGallery1 != null && postwp.postImgGallery1 != "") {
msg.createMedia(postwp.postImgGallery1).then((imgURL)=>ImgGalleyURL.push(imgURL));
}
if (postwp.postImgGallery2 != null && postwp.postImgGallery2 != "") {
msg.createMedia(postwp.postImgGallery2).then((imgURL)=>ImgGalleyURL.push(imgURL));
}
if (postwp.postImgGallery3 != null && postwp.postImgGallery3 != "") {
msg.createMedia(postwp.postImgGallery3).then((imgURL)=>ImgGalleyURL.push(imgURL));
}
if (postwp.postImgGallery4 != null && postwp.postImgGallery4 != "") {
msg.createMedia(postwp.postImgGallery4).then((imgURL)=>ImgGalleyURL.push(imgURL));
}
if (postwp.postImgGallery5 != null && postwp.postImgGallery5 != "") {
msg.createMedia(postwp.postImgGallery5).then((imgURL)=>ImgGalleyURL.push(imgURL));
}
console.log(ImgGalleyURL[0] + "this is the first image loaded");
Thank you all
I think you're looking for Promise.race:
const promises = [];
for (let i=1; i<=5; i++) {
const propName = "postImgGallery" + i;
if (postwp[propName] != null && postwp[propName] != "") {
promises.push(msg.createMedia(postwp[propName]));
}
}
Promise.race(promises).then(firstUrl => {
console.log(firstUrl + "this is the first image loaded");
});
Promise.all(promises).then(imgGalleryURLs => {
console.log("All images ("+ imgGalleryURLs.join(", ") + ") loaded");
});
You were trying to log the first value of the array when none of the promises was fulfilled yet, so it was still empty.
I'm trying to utilize my Google firebase to hold data such a equipment details, work details, and work orders. The idea I had was to hold it all on firebase firestore. In react-native, I wanted to be able to use a separate function file to be able to access the data on firebase, then process it, and then write new information on the firestore. I'm having a bit of trouble temporarily saving the data in an array using the async function with push, and being able to regularly use that information for a variety of functions. The code below just results with too many promises exceptions. Is there a better way to write a script? Or, do you have a way to be able to simplify this?
import firestore from '#react-native-firebase/firestore';
class Worker {
constructor(name, certifications, shift, location) {
this.name = name;
this.certifications = certifications;
this.shift = shift;
this.location = location;
this.currentPosition = location;
this.timeLeftinShift = 8;
this.schedule = [];
this.doneScheduling = false;
}
}
class WorkOrder {
constructor(
eID,
eType,
facility,
location,
priority,
timeStamp,
timeToComplete,
) {
this.eID = eID;
this.eType = eType;
this.facility = facility;
this.location = location;
this.priority = priority;
this.timeStamp = timeStamp;
this.timeToComplete = timeToComplete;
this.done = false;
}
}
class Facility {
constructor(name, location, maxOcc) {
this.name = name;
this.location = location;
this.maxOcc = maxOcc;
this.curOcc = 0;
}
}
//assigns a worker
export function assignWorker() {
var tempWorkers = [];
async function workers() {
const workersCollection = await firestore()
.collection('workers')
.get()
.then(async (querySnapshot) => {
querySnapshot.forEach(async (documentSnapshot) => {
let temp = new Worker(
documentSnapshot.id,
documentSnapshot.data().Certifications,
documentSnapshot.data().Shift,
[
documentSnapshot.data().Location.longitude,
documentSnapshot.data().Location.latitude,
],
);
tempWorkers.push(temp);
});
});
return tempWorkers;
}
var tempFacilities = [];
async function Facilities() {
var tempFacilities = [];
const facilitiesCollection = await firestore()
.collection('facility')
.get()
.then(async (querySnapshot) => {
querySnapshot.forEach(async (documentSnapshot) => {
let temp = new Facility(
documentSnapshot.id,
[
documentSnapshot.data().Location.longitude,
documentSnapshot.data().Location.latitude,
],
documentSnapshot.data()['Max Occupancy'],
);
tempFacilities.push(temp);
});
});
return tempFacilities;
}
var tempWorkOrders = [];
async function workOrders() {
var tempWorkOrders = [];
const workOrdersCollection = await firestore()
.collection('sample work order')
.get()
.then(async (querySnapshot) => {
querySnapshot.forEach(async (documentSnapshot) => {
let temp = new WorkOrder(
documentSnapshot.data()['Equipment ID'],
documentSnapshot.data()['Equipment Type'],
documentSnapshot.data().Facility,
getFCoord(documentSnapshot.data().Facility, tempFacilities),
documentSnapshot.data()['Priority(1-5)'],
documentSnapshot.data()['Submission Timestamp'],
documentSnapshot.data()['Time to Complete'],
);
tempWorkOrders.push(temp);
});
});
return tempWorkOrders;
}
// final part
console.log('Reached Assigned Schedule');
workOrders().then((y) => {
workers().then((z) => {
assignSchedule(z, y);
for (let i = 0; i < z.length; ++i) {
firestore()
.collection('schedules')
.doc(tempWorkers[i].name)
.set({
schedule: tempWorkers[i].schedule,
})
.then(() => {});
}
});
});
console.log('Reached Assigned Schedule');
function getFCoord(inFacility) {
Facilities().then((x) => {
for (let i = 0; i < x.length; ++i) {
if (inFacility === x[i].name) {
// //console.log(
// // 'fCoord lat: ',
// // x[i].location[0],
// // ', fCoord long: ',
// x[i].location[1],
// );
return [x[i].location[0], x[i].location[1]];
}
}
});
}
// if a task is completed, we remove the work order
// if a task isn't completed by shift end, we subtract the time spent on the task and change the work order to reflect that
// two points (long, lat) distance function
function distBetweenTwoGeoPoints(lat, long, lat2, long2) {
const earthRadius = 6371;
let deltaPhi = ((lat2 - lat) * Math.PI) / 180;
let deltaLambda = ((long2 - long) * Math.PI) / 180;
let phi1 = (lat * Math.PI) / 180;
let phi2 = (lat2 * Math.PI) / 180;
let a =
Math.sin(deltaPhi / 2) ** 2 +
Math.cos(phi1) * Math.cos(phi2) * Math.sin(deltaLambda / 2) ** 2;
let c = 2 * Math.atan(Math.sqrt(a), Math.sqrt(1 - a));
return earthRadius * c;
}
// initial schedule for the day will come from all work orders that haven't been completed before their shift
//based upon technician certification we'd filter the work orders applicable
// letiables for optimization
// probability of failure
// location distance
// priority
// function -> ()
//filter each task by worker which can complete them
//for each worker, filter tasks that they can complete
// urgency score will be function of priority and time since task has been requested
// real time will be time takes to complete + travel time
// multiplier will be a function of how long a task will take and how much time is left in that person's shift
function score(workorder) {
//return workorder.priority * timeSinceRequest(workorder.timeStamp);
return workorder.priority;
}
function listOfTasksPerWorker() {
workOrders().then((Workers) => {
workers().then((workorders) => {
let numWorkers = Workers.length;
let numTasks = workorders.length;
let possibleTasks = [];
for (let i = 0; i < numWorkers; ++i) {
let taskList = [];
for (let j = 0; j < numTasks; ++j) {
//console.log("equipment " + workorders[j].eType);
for (let k = 0; k < workers[i].certifications.length; ++k) {
//console.log("certif " + workers[i].certifications[k]);
if (workorders[j].eType === workers[i].certifications[k]) {
//check certifications
taskList.push(workorders[j]);
}
}
}
possibleTasks.push(taskList);
}
return possibleTasks;
});
});
}
//given task will be apart of taskList
function removeTask(task, taskList) {
let newArr = [];
for (let i = 0; i < taskList.length; ++i) {
if (task.eID === taskList[i].eID) {
newArr = taskList.slice(i, i + 1);
return newArr;
}
}
}
// while workers have shift
// go through workorders
// terminates either when all the workers shifts are full or when there are no work orders
function assignSchedule() {
workOrders().then((Workers) => {
workers().then((workorders) => {
let numDone = 0;
while (numDone < Workers.length && workorders.length > 0) {
console.log('before choose workers');
chooseWorkers(Workers, workorders);
console.log('pass choose workers');
for (let i = 0; i < Workers.length; ++i) {
if (Workers[i].timeLeftinShift <= 0) {
++numDone;
}
}
}
});
});
}
//change time left in workshift
//change location of worker
//say task is assigned, and remove from workorder IF COMPLETED
function assignTask(worker, workorder) {
workOrders().then((workorders) => {
let taskTime =
workorder.timeToComplete +
timeToGetFacility(worker.location, workorder.location);
if (worker.timeLeftinShift < taskTime) {
worker.timeLeftinShift = 0;
workorder.timeToComplete =
worker.timeToComplete - worker.timeLeftinShift;
} else {
worker.timeLeftinShift = worker.timeLeftinShift - taskTime;
workorder.timeToComplete = 0;
workorders = removeTask(workorder, workorders);
}
worker.location = workorder.location;
worker.schedule.push(workorder);
console.log('assign task');
});
}
function chooseWorkers() {
workOrders().then((Workers) => {
workers().then((workorders) => {
for (let i = 0; i < Workers.length; ++i) {
let keep = true;
let bestTaskw1;
let bestTaskw2;
let worker1Tasks = listOfTasksPerWorker(Workers, workorders)[i];
console.log('tasks: ', worker1Tasks);
let schedule = oneSchedule(Workers[i], worker1Tasks);
if (!schedule[0].length) {
break;
} else {
bestTaskw1 = schedule[0][0];
}
console.log('pass schedule');
if (!Workers[i].doneScheduling) {
for (let j = i + 1; j < Workers.length; ++j) {
if (!Workers[j].doneScheduling) {
let worker2Tasks = listOfTasksPerWorker(Workers, workorders)[j];
let schedule2 = oneSchedule(Workers[j], worker2Tasks);
if (!schedule2[0].length) {
break;
} else {
bestTaskw2 = schedule[0][0];
if (bestTaskw1.eID === bestTaskw2.eID) {
let w1SecondSchedule = oneSchedule(
Workers[i],
removeTask(bestTaskw1, worker1Tasks),
);
let w2SecondSchedule = oneSchedule(
Workers[j],
removeTask(bestTaskw1, worker1Tasks),
);
if (
bestTaskw1[1] - w1SecondSchedule[1] <
bestTaskw2[1] - w2SecondSchedule[1]
) {
keep = false;
i = i - 1;
//fix next line
worker1Tasks = removeTask(bestTaskw1, worker1Tasks);
break;
}
}
}
}
}
if (keep) {
assignTask(Workers[i], bestTaskw1, workorders);
}
}
}
});
});
}
function timeToGetFacility(point1, point2) {
const avgSpdKm = 70;
let timeToGetThere =
distBetweenTwoGeoPoints(point1[0], point1[1], point2[0], point2[1]) /
avgSpdKm;
return timeToGetThere;
}
function oneSchedule(worker1, worker1Tasks) {
let time1 = worker1.timeLeftinShift;
let total1 = 0;
let tasks1 = [];
let tempLocation = worker1.location;
while (time1 > 0) {
let bestOrder;
let bestOrderInd;
let bestScorePerHour = 0;
let travelTime = 0;
let bestTravelTime = 0;
console.log('before for');
console.log(worker1Tasks.length.toString());
for (let i = 0; i < worker1Tasks.length; ++i) {
console.log('before if');
console.log('test: ', i, worker1Tasks.length);
if (!worker1Tasks[i].done) {
console.log('after if');
let tempScorePerHour = 0;
console.log('location: ', tempLocation[0], tempLocation[1]);
travelTime = timeToGetFacility(
tempLocation,
worker1Tasks[i].location,
);
console.log('travel time: ', travelTime);
if (time1 - (worker1Tasks[i].timeToComplete + travelTime) < 0) {
tempScorePerHour =
(score(worker1Tasks[i]) *
((time1 - travelTime) / worker1Tasks[i].timeToComplete)) /
time1;
} else {
tempScorePerHour =
score(worker1Tasks[i]) /
(worker1Tasks[i].timeToComplete + travelTime);
}
console.log('score: ', score(worker1Tasks[i]));
console.log('temp: ', tempScorePerHour);
if (tempScorePerHour > bestScorePerHour) {
bestScorePerHour = tempScorePerHour;
bestOrder = worker1Tasks[i];
bestOrderInd = i;
bestTravelTime = travelTime;
}
}
}
if (bestScorePerHour > 0) {
worker1Tasks.splice(bestOrderInd, 1);
//bestOrder.done = true;
tasks1.push(bestOrder);
console.log(bestOrder.eID);
console.log(bestScorePerHour);
if (time1 - (bestOrder.timeToComplete + bestTravelTime) < 0) {
total1 += bestScorePerHour * time1;
time1 = 0;
} else {
total1 += score(bestOrder);
time1 -= bestOrder.timeToComplete + bestTravelTime;
}
console.log(bestOrder.timeToComplete);
tempLocation = bestOrder.location;
} else {
break;
}
}
return [tasks1, total1];
}
}
I want to get the last deviceId.
Please try the following code on a smartphone.
https://www.ofima.ch/file1.html
Inside the function "getConnectedDevices" the variable deviceId ok.
But outside is returned a promise and not the variable deviceId.
How can I get the variable deviceId ?
Thanks
Miche
Explanation:
You need to wrap your alert in an async function and use await. Also to take the value from the promise you needed .then(). Hope the below helps.
Original code:
async function getConnectedDevices() {
var index;
const devices = await navigator.mediaDevices.enumerateDevices();
for (var i=0; i<devices.length; i++) {
if (devices[i].kind == "videoinput") {
index = i;
}
}
var deviceId = devices[index].deviceId;
alert('deviceId is ok: ' + deviceId);
return (deviceId);
}
const deviceId = getConnectedDevices();
alert('deviceId is not defined, why ?: ' + deviceId);
New code:
async function getConnectedDevices() {
let index;
const devices = await navigator.mediaDevices.enumerateDevices();
for (let i=0; i < devices.length; i++) {
console.debug(devices[i]);
if (devices[i].kind == "videoinput") {
index = i;
}
}
console.log('deviceId is ok: ', devices[index]);
return devices[index].deviceId;
}
(async() => {
const deviceId = await getConnectedDevices().then();
alert(`deviceId: ${deviceId}`);
})();
And a quick hack for storing the deviceId in the window
console.log('globalDeviceId should be undefined', window.globalDeviceObj);
async function getConnectedDevices() {
let index;
const devices = await navigator.mediaDevices.enumerateDevices();
for (let i = 0; i < devices.length; i++) {
console.debug(devices[i]);
if (devices[i].kind == "videoinput") {
index = i;
}
}
console.log('deviceId is ok', devices[index]);
return devices[index];
}
function getDeviceId() {
(async() => {
window.globalDeviceObj = await getConnectedDevices().then();
console.log(`globalDeviceId set: ${JSON.stringify(window.globalDeviceObj)}`);
})();
}
function tick() {
if(typeof window.globalDeviceObj === 'undefined'){
requestAnimationFrame(tick);
}else {
alert(`globalDeviceId get: ${JSON.stringify(window.globalDeviceObj)}, with deviceId: ${(window.globalDeviceObj.deviceId)}`)
}
}
function init() {
tick();
getDeviceId();
}
init();
I have a computed property (filteredSyms) that depends on the asynchronous computed property (allSynonyms). I am using async-computed plugin for this:
https://www.npmjs.com/package/vue-async-computed.
However, when the data gets updated the computed property doesn't wait until the result of the async property update. Therefore, I receive not up to date information. Then after the async property actually return new value computed property doesn't run update again.
How can I make it work the way that computer property waits until there is a result from the async computed property?
The code is below:
asyncComputed: {
async allSynonyms() {
let allSyns = await this.$axios.$post('/db/sym/synonyms', this.model.syms);
return allSyns;
}
},
computed: {
filteredSyms() {
let that = this;
let allSyn = this.allSynonyms;
let exactMatch = this.symsByRating.filter(
function (v) {
let isExactMatch = v.title.toLocaleLowerCase().indexOf(that.searchString.toLocaleLowerCase()) >= 0;
return !that.idsToFilter.includes(v.id) && isExactMatch
&& (!that.currentBodyPart || v.bodyParts.indexOf(that.currentBodyPart) >= 0)
&& that.hasMoreSubsyms(v)
&& (!allSyn || !that.containsObject(v, allSyn))
&& (v.sex == that.model.sex || v.sex == 'NA');
});
let partialList = [];
exactMatch.forEach(ex => partialList.push({n: 100, sym: ex}));
for (let sym of this.symsByRating ) {
let searchWords = this.searchString.toLocaleLowerCase().split(' ');
let symWords = sym.title.toLocaleLowerCase().split(' ');
let n = 0;
let isPartialMatch = false;
symLoop:for (let symWord of symWords) {
symWord = symWord.substring(0, symWord.length - 1);
for (let searchWord of searchWords) {
// don't count last letters of the words
searchWord = searchWord.substring(0, searchWord.length - 1);
if (searchWord.length > 2 && symWord.indexOf(searchWord) >= 0) {
n++;
isPartialMatch = true;
}
}
}
if (exactMatch.indexOf(sym) < 0 && isPartialMatch
&& (!this.currentBodyPart || sym.bodyParts.indexOf(this.currentBodyPart) >= 0)
&& this.hasMoreSubsyms(sym)
&& (!allSyn || !this.containsObject(sym, allSyn))
&& (sym.sex == that.model.sex || sym.sex == 'NA')) {
partialList.push({n: n, sym: sym});
}
}
partialList.sort(function(obj1, obj2) {
return obj2.n - obj1.n;
});
if (this.searchString && this.searchString != '') {
partialList = this.filterSynonyms(partialList);
}
let fs = partialList.map(ws => ws.sym);
console.dir(fs);
return fs;
}
}
A lot of stuff is going on the filtered method, but I guess the main point here that it is using this.allSynonyms to do the check but it is not updated at the time filteredSyms is executed.
Thanks for your suggestions!
(I haven't really tested this out, but it should work.)
vue-async-computed does provide the status in this.$asyncComputed.allSynonyms.success.
try adding this.$asyncComputed.allSynonyms.success as a dependencies to filteredSyms and it should update when success state change.
Hi I have 3 tables of which, each one is child of another. I wrote a method to fetch from sqllite db as follows
public downloadFromOfflineDB(db,testSO){
var observableBatch = [];
observableBatch.push(db.executeSql("select * from TMP_AUD WHERE CRE_BY=? AND AUD_NUMBER=? ",
[localStorage.getItem("user_name"), testSO.auditNumber]).then(
response => {
this._util.logData('In downloadPendingInstancesForSyncFromOfflineDB- folder'+response.rows.length+'ID= '+response.rows.item(0).FLD_NUMBER);
if (response && response.rows && response.rows.length > 0) {
if (response && response.rows && response.rows.length > 0) {
var FLD_NUMBER = response.rows.item(0).FLD_NUMBER;
var folderArray = []
observableBatch.push(db.executeSql("select * from TMP_FOLDER WHERE CRE_BY=? AND FLD_NUMBER=? ",
[localStorage.getItem("user_name"), FLD_NUMBER]).then(
a => {
this._util.logData('In downloadPendingInstancesForSyncFromOfflineDB-TMP_FOLDER'+a.rows.length);
if (a && a.rows && a.rows.length > 0) {
for (let i = 0; i < a.rows.length; i++) {
var folderObj = {
folderName: a.rows.item(i).FLD_NAME,
files:[]
}
var FLD_NAME = a.rows.item(i).FLD_NAME
this._util.logData('In downloadPendingInstancesForSyncFromOfflineDB-TMP_FOLDER '+FLD_NAME);
observableBatch.push( db.executeSql("select * from TMP_FILES WHERE CRE_BY=? AND FLD_NAME=? ",
[localStorage.getItem("user_name"), FLD_NAME]).then(
b => {
this._util.logData('In downloadPendingInstancesForSyncFromOfflineDB-TMP_FILES'+b.rows.length);
var fileArray = [];
if (b && b.rows && b.rows.length > 0) {
for (let j = 0; j < b.rows.length; j++) {
var fileSO = {
compliance: b.rows.item(j).COMPLIANCE,
remarks: b.rows.item(j).REMARKS,
fileName: b.rows.item(j).FILE_NAME,
title: b.rows.item(j).TITLE
}
);
fileArray.push(fileSO);
}}
folderObj.files=fileArray;
}).catch(
e => {
this._util.logData('For sync error'+JSON.stringify(e));
return Observable.throw("An error occurred during sync");
})
);
folderArray.push(folderObj);
}}
}).catch(
e => {
this._util.logData('For sync error'+JSON.stringify(e));
return Observable.throw("An error occurred during sync");
})
);
}
}
testSO.folderArray = folderArray;
this._util.logData('Candidate for selected for sync' + JSON.stringify(testSO));
})
);
return Observable.forkJoin(observableBatch);
}
The issue here is below method is not waiting for all the calls to finish
public getFiles(testSO) {
return Observable.create(observer => {
this.platform.ready().then(() => {
this.sqlite.create({
name: 'offline.db',
location: 'default'
}).then((db: SQLiteObject) => {
this.downloadFromOfflineDB(db, testSO).subscribe(c => {
observer.next(c[0]);//This is undefined
observer.complete();
},
error => {
observer.error("An error occurred sync files.");
});
});
});
});
}
First method is executing, while second method returns before first execution is complete and I am not getting my object testSO populated. Can someone please guide me and tel me what I am doing wrong here.I used observable fork Join.
Looks like you are calling Observable.forkJoin(observableBatch) with only one item - result of db.executeSql. When you add more items later on it doesn't affect forkJoin.