React Native:同步运行函数 [英] React Native: synchronously run functions

查看:34
本文介绍了React Native:同步运行函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是OOP的新手。我对Promise /异步/同步运行功能的了解很简单。非常感谢您的时间和关注!



这是React-Native文档中的示例:



  async函数getMoviesFromApi(){试试{让response =等待fetch('https://facebook.github.io/react-native/movies .json');让responseJson =等待response.json();返回responseJson.movi​​es; } catch(error){console.error(error); }}  



根据上面的代码,getMoviesFromApi被声明为异步功能。这意味着它将一个接一个地执行功能。对?



它将首先等待获取完成,然后调用response.json,对吗?



<我没有几个函数,这些函数通过获取从服务器获取数据,然后将它们插入sqlite数据库。因此,他们什么也不会返回。



在上面的示例中,fetch返回了一些内容。但是我的职能不是。因此,我可以使用这种结构来使javascript运行我的函数吗?



  let query = [];导出默认类Main扩展了Component(){构造函数(props){super(props); } componentWillMount(){this.getBookable(); this.getBooked(); this.runQuery(); this.redirectUser(); ////我需要此函数才能运行。并非每次都在同一时间,一个接一个}} getBookable(){让fetchedData = fetch(); ///从远程服务器query.push('INSERT INTO bookable(data)VALUES('+ fetchedData +')')中获取数据; } getBooked(){让fetchedData = fetch(); ///从远程服务器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。result:',results);},(err)=> {console.log('执行查询时出了点问题',query [i],'error is',err);});}); }} redirectUser(){Actions.tabbar({type:‘reset’}}); ////使用redux。将用户重定向到另一页}}  


首先,我获得可预订的课程,然后预定课程,将其插入数据库,然后通过redux
将用户重定向到另一个页面。






UPDATE:



根据@Bergi更新代码:
这是正确的方法吗?



 从'react'导入React,{Component,PropTypes};从'react-native'导入{ActivityIndi​​cator,StyleSheet,Text,View,NetInfo,AlertIOS,}; var SQLite = require('react-native-sqlite-storage'); var loading = require( ./ Loading); var DeviceInfo = require('react-native-device-info');从'react- native-router-flux'; var LOADING = {}; var db = SQLite.openDatabase({name: oc.db,location:'default'});从 react- native-code-push;从'react-native-i18n'导入I18n;从'./translations'导入翻译; I18n.fallbacks = true;导出默认类Grab扩展了Component {Constructor(props){ this.state = {条款:’,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(抢夺:运行手动代码推送更新); 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 {让结果=等待tx.executeSql(q,[]); console.log('Query' ,q,'执行的结果:',结果); for(让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,活动:results.rows.item(ind).active,名字:results.rows.item(ind).firstName,lastName :result.rows.item(ind).lastName,accessToken:results.rows.item(ind).access_token,主持人:results.rows.item(ind).host,};}} catch(err){console.log (执行查询时出了点问题,q,错误为,err);}})));));返回用户列表; }异步getBookable(users){let results = []; for(let n = 0; n< users.length; n ++){尝试{让host = users [n] .host;让access_token = users [n] .access_token;让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}));让responseData =等待response.json(); ////获取容器详细信息if(responseData.container.length> 0){for(let i = 0; i< responseData.container.length; i ++){让cnid = responseData.container [i] .nid;让ctitle = responseData.container [i] .title; result.push(插入容器C(userId,nid,title)值(' + userId +',' + cnid +’,’ + ctitle +’)); ////为每个容器获取以下课程:(让j = 0; j< responseData.container [i] .course.length; j ++){let course_id = responseData.container [i] .course [j] .nid;让title = responseData.container [i] .course [j] .title;让成本= responseData.container [i] .course [j] .cost; let status = responseData.container [i] .course [j] .status;让周期= responseData.container [i] .course [j] .period.time_sys; ////获取每个课程的详细信息,尝试{let resp = await fetch(host +'event / course_detail /'+ course_id,{方法:'POST',标头:{'Accept':'application / json','Content -Type':'application / json','language':DeviceInfo.getDeviceLocale(),'Authorization':'Bearer'+ access_token}));让respData =等待resp.json();让desc = respData.data.content [0] .value;设容量= respData.data.content [1] .value;让图像= respData.data.image;让状态= respData.data.book;让取消= respData.data.cancel;让cd = responseData.data.dates; results.push( INSERT INTO课程(userId,course_id,container_nid,标题,成本,状态,期限,desc,容量,图像,取消)VALUES(' + userId +',' + course_id +','  + cnid +',' +标题+',' +成本+',' +状态+',' +句点+',' + desc +',' +容量+',' +图片+',' +取消+')); ////获取每门课程的授课日期,用于(let a = 0; a< cd.length; a ++){let sdate = cd [a] .start_time.split();让edate = cd [a] .end_time.split(); results.push(将演讲插入(用户ID,课程ID,标题,开始时间,结束时间,开始日期,结束日期,房间,教师)值(' +用户ID +',' +课程ID +',' + cd [ a] .title +',' + sdate [1] +',' + edate [1] +',' + sdate [0] +',' + edate [0] + ',' + cd [a] .room +',' + cd [a] .teacher +')); } ////结束课程的授课日期返回true; } catch(error){console.error(error); } ////结束课程的详细信息} ////结束容器的课程}} ////结束容器的详细信息返回true; } catch(error){console.error(error); }}} redirectUser(){Actions.tabbar({type:‘reset’}}); } async runQuery(query){等待db.transaction(tx => {返回Promise.all(query.map(async(q)=> {尝试{让结果=等待tx.executeSql(q,[]); console.log('Query',q,'Executed。results:',results);} catch(err){console.log('执行查询时出了点问题',q,'error is',err);} }));});返回true; }异步函数GrabData(){试试{让用户=等待getUsers(); // // [课程,注册,评估] =等待Promise.all([getCourses(用户),getRegister(用户),getEvaluation(用户)]);让[课程] =等待Promise.all([getCourses(users)]); //让查询= [课程,注册,评估];让查询= [课程];等待runQuery([从containerC删除,从课程删除,从讲座删除,从容器R删除,从注册删除,从讲座删除,从评估删除,从字段删除 ]);等待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);  



我正在使用react-native-sqlite-storage:
https://github.com/andpor/react-native-sqlite-storage

解决方案


getMoviesFromApi 被声明为异步功能


否。这仅意味着它在被调用时将返回一个Promise,并且您可以在函数主体中使用 await 运算符。


它将首先等待获取完成,然后调用response.json,对吗?


是,因为它使用 await 停止对该方法的评估,直到承诺解决为止。


我有几个函数,这些函数通过获取从服务器获取数据,然后将它们插入sqlite数据库。因此,他们什么也不会退回。


他们应该退还诺言-即使诺言什么,他们仍然可以等待。



但是在您的情况下,他们实际上应该返回某些内容。您的全局静态 query 数组是一个可怕的反模式。而不是用查询填充查询,每个方法都应返回查询(对查询的承诺),然后可以根据实例和调用将其传递给执行程序。只有然后使用 transaction 才真正有意义。



您的代码应如下所示:

 类Main扩展Component(){

async getBookable(){
var response = await lfetch(host,{
方法: POST,
标头:…
});
var responseData =等待response.json();
返回插入可预订(数据)值( + responseData +))); //注意SQL注入!!!
}

getBooked(){
//完全相同-此处没有异步/等待:
return fetch(host,{
// ^^^^^^重要-返回一个promise
方法:'POST',
标头:…
})
.then(response => response.json() )
.then(responseData => {
return'INSERT INTO booked(data)VALUES('+ responseData +')';
});
//不捕捉任何东西,不调用`done`-只返回承诺链
//错误将在try / catch中处理
}

异步runQuery(query){
等待db.transaction(tx => {
return Promise.all(query.map(async(q)=> {
试试{
let results = await tx.executeSql(q,[]);
console.log('Query',q,'Executed。results:',results);
} catch(err){
console.log('执行查询时出了点问题',q,'错误是',err);
}
}));
} );
返回true;
}

异步函数getStore(){
try {
//实际上,您可以并行获取它们,对吧?
let [可预订,已预订] =等待Promise.all([getBookable(),getBooked()]);
let query = [可预订,已预订];
等待runQuery(query);
redirectUser();
} catch(error){
console.error(error);
}
}
}


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

解决方案

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

这篇关于React Native:同步运行函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆