Friday, May 10, 2024
 Popular · Latest · Hot · Upcoming
191
rated 0 times [  198] [ 7]  / answers: 1 / hits: 25488  / 8 Years ago, mon, october 10, 2016, 12:00:00

I'm new to OOP. My knowledge of promises/asynchronously/synchronously running functions is simply basic. I'd really appreciate your time and attention!



This is the example from React-Native docs:





async function getMoviesFromApi() {
try {
let response = await fetch('https://facebook.github.io/react-native/movies.json');
let responseJson = await response.json();
return responseJson.movies;
} catch(error) {
console.error(error);
}
}





As i understand from code above, getMoviesFromApi is declared as async function. which means it will execute functions one after other. Right? please correct me if not!



it will first wait for fetch to finish then call response.json, right?



I have few functions, which get data from a server via fetch, then insert them to sqlite database. so they don't return anything.



in example above, fetch returns something. but my functions, not. so, can i use this structure to make javascript run my functions consequently? what is the best practice / right solution to achieve this?





let query = [];
export default class Main extends Component(){
constructor(props){
super(props);
}

componentWillMount(){
this.getBookable();
this.getBooked();
this.runQuery();
this.redirectUser();
//// i need this functions to run consequently. not all in same time, one after eachother
}

getBookable(){
let fetchedData = fetch(); /// Fetchs data from remote server
query.push('INSERT INTO bookable (data) VALUES (' + fetchedData + ')');
}

getBooked(){
let fetchedData = fetch(); /// Fetchs data from remote server
query.push('INSERT INTO booked (data) VALUES (' + fetchedData + ')');
}

runQuery(){
for(let i=0; i < query.length; i++){
db.transaction((tx) => {
tx.executeSql(query[i],[], (tx, results) => {
console.log('Query', query[f], 'Executed. results:', results);
}, (err)=>{
console.log('Something went wrong while executing query',query[i],'error is', err);
});
});
}
}

redirectUser(){
Actions.tabbar({type: 'reset'});
//// Using redux. redirect user to another page
}

}




First, i get bookable courses, then booked courses, insert them to database, then redirect user to another page via redux
How should i update my code?






UPDATE :



updated code according to @Bergi :
is this the right way?





import React, {Component, PropTypes} from 'react';
import {
ActivityIndicator,
StyleSheet,
Text,
View,
NetInfo,
AlertIOS,
} from 'react-native';

var SQLite = require('react-native-sqlite-storage');
var Loading = require(./Loading);
var DeviceInfo = require('react-native-device-info');
import { Actions } from 'react-native-router-flux';
var LOADING = {};
var db = SQLite.openDatabase({name : oc.db, location: 'default'});
import CodePush from react-native-code-push;
import I18n from 'react-native-i18n';
import translations from './translations';
I18n.fallbacks = true;

export default class Grab extends Component{
constructor(props) {
super(props);
this.state = {
terms: '',
isLoading: false,
isConnected: null,
coursesFetched: false,
registerFetched: false,
};
}

componentWillMount() {

NetInfo.isConnected.fetch().then(isConnected => {
this.setState({
isConnected: isConnected
});
});

NetInfo.isConnected.addEventListener(
'change',
isConnected => {
this.setState({
isConnected: isConnected
});
console.log('Grab: internet status is', this.state.isConnected);
this.sync();
}
);

this.GrabData();

}

toggleAllowRestart() {
this.state.restartAllowed
? CodePush.disallowRestart()
: CodePush.allowRestart();

this.setState({ restartAllowed: !this.state.restartAllowed });
}

sync() {
console.log(Grab: Running manual code push update);
CodePush.sync(
{
installMode: CodePush.InstallMode.IMMEDIATE,
updateDialog: false
},
);
}

async getUsers(){
let userlist = [];
let query = [SELECT * FROM users];
await db.transaction(tx => {
return Promise.all(query.map(async (q) => {
try {
let results = await tx.executeSql(q, []);
console.log('Query', q, 'Executed. results:', results);
for(let ind = 0; ind < len; ind++ ){
userlist[ind] = {
userId: results.rows.item(ind).userId,
userName: results.rows.item(ind).userName,
userMail: results.rows.item(ind).userMail,
active: results.rows.item(ind).active,
firstName: results.rows.item(ind).firstName,
lastName: results.rows.item(ind).lastName,
accessToken: results.rows.item(ind).access_token,
host: results.rows.item(ind).host,
};
}
} catch(err) {
console.log('Something went wrong while executing query', q, 'error is', err);
}
}));
});
return userlist;
}

async getBookable(users){
let results = [];
for(let n=0; n < users.length; n++){
try {
let host = users[n].host;
let access_token = users[n].access_token;
let userId = users[n].userId;
let response = await fetch(host + 'event/my_events', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'language': DeviceInfo.getDeviceLocale(),
'Authorization': 'Bearer ' + access_token
}
});
let responseData = await response.json();
//// Get container details
if(responseData.container.length > 0){
for(let i=0; i < responseData.container.length; i++){
let cnid = responseData.container[i].nid;
let ctitle = responseData.container[i].title;
results.push(
INSERT INTO containersC (userId, nid, title) VALUES (' + userId + ',' + cnid + ', ' + ctitle + ')
);
//// Get courses for each container
for(let j=0; j < responseData.container[i].course.length; j++){
let course_id = responseData.container[i].course[j].nid;
let title = responseData.container[i].course[j].title;
let cost = responseData.container[i].course[j].cost;
let status = responseData.container[i].course[j].status;
let period = responseData.container[i].course[j].period.time_sys;
//// Get details for each course
try {
let resp = await fetch(host + 'event/course_detail/' + course_id, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'language': DeviceInfo.getDeviceLocale(),
'Authorization': 'Bearer ' + access_token
}
});
let respData = await resp.json();

let desc = respData.data.content[0].value;
let capacity = respData.data.content[1].value;
let image = respData.data.image;
let status = respData.data.book;
let cancel = respData.data.cancel;
let cd = responseData.data.dates;

results.push(
INSERT INTO courses (userId, course_id, container_nid, title, cost, status, period, desc, capacity, image, cancel) VALUES (' + userId + ',' + course_id + ', ' + cnid + ', ' + title + ', ' + cost + ', ' + status + ', ' + period + ', ' + desc + ', ' + capacity + ', ' + image + ', ' + cancel + ')
);

//// Getting lecture dates for each course
for(let a=0; a < cd.length; a++){
let sdate = cd[a].start_time.split( );
let edate = cd[a].end_time.split( );
results.push(
INSERT INTO lectures (userId, course_id, title, start_time, end_time, start_date, end_date, room, teacher) VALUES (' + userId + ',' + course_id + ', ' + cd[a].title + ', ' + sdate[1] + ', ' + edate[1] + ', ' + sdate[0] + ', ' + edate[0] + ', ' + cd[a].room + ', ' + cd[a].teacher + ')
);
}
//// End getting lecture dates for courses
return true;
} catch(error) {
console.error(error);
}
//// End getting details for courses
}
//// End getting courses for containers
}
}
//// End getting container details
return true;
} catch(error) {
console.error(error);
}
}
}

redirectUser(){
Actions.tabbar({type: 'reset'});
}

async runQuery(query) {
await db.transaction(tx => {
return Promise.all(query.map(async (q) => {
try {
let results = await tx.executeSql(q, []);
console.log('Query', q, 'Executed. results:', results);
} catch(err) {
console.log('Something went wrong while executing query', q, 'error is', err);
}
}));
});
return true;

}

async function GrabData(){
try {
let users = await getUsers();
//let [courses, register, evaluation] = await Promise.all([getCourses(users), getRegister(users), getEvaluation(users)]);
let [courses] = await Promise.all([getCourses(users)]);
//let query = [courses, register, evaluation];
let query = [courses];
await runQuery([DELETE FROM containersC, DELETE FROM courses, DELETE FROM lectures, DELETE FROM containersR, DELETE FROM register, DELETE FROM lectures, DELETE FROM evaluations, DELETE FROM fields]);
await runQuery(query);
this.redirectUser();
} catch(error){
console.log(error);
}
}


render() {

return(
<View style={styles.container}><Loading/></View>
);
}

}

var styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: #fff,
flexDirection: column,
},
});

Grab = CodePush(Grab);





I'm using react-native-sqlite-storage :
https://github.com/andpor/react-native-sqlite-storage


More From » reactjs

 Answers
40

getMoviesFromApi is declared as async function. which means it will execute functions one after other.




No. That only means that it will return a promise when called, and that you can use the await operator in the function body.




it will first wait for fetch to finish then call response.json, right?




Yes, because it uses await to stop evaluation of the method until the promise resolves.




I have few functions, which get data from a server via fetch, then insert them to sqlite database. so they don't return anything.




They should return promises - even if they're promises for nothing, they still could be awaited.



But in your case, they actually should return something. Your global static query array is a horrible antipattern. Instead of filling it with queries, each method should return (a promise for) a query, which then can be passed to the executor on a per-instance and per-call basis. Only then using a transaction actually begins to make sense.



Your code should look like this:



class Main extends Component() {

async getBookable(){
var response = await lfetch(host, {
method: 'POST',
headers: …
});
var responseData = await response.json();
return 'INSERT INTO bookable (data) VALUES (' + responseData + ')'); // beware of SQL injections!!!
}

getBooked(){
// the very same - here written without async/await:
return fetch(host, {
// ^^^^^^ important - return a promise
method: 'POST',
headers: …
})
.then(response => response.json())
.then(responseData => {
return 'INSERT INTO booked (data) VALUES (' + responseData + ')';
});
// don't `catch` anything, don't call `done` - just return the promise chain
// errors will be handled in the try/catch below
}

async runQuery(query) {
await db.transaction(tx => {
return Promise.all(query.map(async (q) => {
try {
let results = await tx.executeSql(q, []);
console.log('Query', q, 'Executed. results:', results);
} catch(err) {
console.log('Something went wrong while executing query', q, 'error is', err);
}
}));
});
return true;
}

async function getStore() {
try {
// actually you can fetch these in parallel, right?
let [bookable, booked] = await Promise.all([getBookable(), getBooked()]);
let query = [bookable, booked];
await runQuery(query);
redirectUser();
} catch(error) {
console.error(error);
}
}
}

[#60450] Thursday, October 6, 2016, 8 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
alli

Total Points: 409
Total Questions: 101
Total Answers: 105

Location: The Bahamas
Member since Tue, Apr 27, 2021
3 Years ago
alli questions
Sat, Apr 23, 22, 00:00, 2 Years ago
Mon, May 18, 20, 00:00, 4 Years ago
Tue, Mar 24, 20, 00:00, 4 Years ago
Fri, Jan 24, 20, 00:00, 4 Years ago
;