Ataomega Ataomega - 2 months ago 46
React JSX Question

React Native: synchronously run functions

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?



var SQLite = require('react-native-sqlite-storage');
var db = SQLite.openDatabase({name : "oc.db", location: 'default'});

export default class Main extends Component(){
constructor(props){
super(props);
}

componentWillMount(){
this.getStore();
}

getBookable(){
fetch(host, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'language': DeviceInfo.getDeviceLocale(),
'Authorization': 'Bearer ' + access_token
}
})
.then((response)=> {
return response.json();
})
.then((responseData) => {
let query = 'INSERT INTO bookable (data) VALUES (' + responseData + ')';
return query;
})
.catch((err)=> {
console.log(,err);
})
.done();
}

getBooked(){
fetch(host, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'language': DeviceInfo.getDeviceLocale(),
'Authorization': 'Bearer ' + access_token
}
})
.then((response)=> {
return response.json();
})
.then((responseData) => {
let query = 'INSERT INTO booked (data) VALUES (' + responseData + ')';
return query;
})
.catch((err)=> {
console.log(,err);
})
.done();
}

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

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

async function getStore() {
try {
let bookable = await getBookable();
let booked = await getBooked();
let runquery = await runQuery([bookable, booked]);
redirectUser();
} catch(error) {
console.error(error);
}
}

}





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

Answer

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);
    }
  }
}