如何在异步函数之间共享变量?

How to share a variable between async functions?

我是 React-Native 的新手,我很困惑如何拥有一个可以被文件中所有函数访问的变量,而不是在 class.

我的问题是我在 taskFour() 中分配了存储,我希望该值在 runDemo() 中 returned 但出于某种原因,当我在 runDemo( ) 它return未定义!

我已经定义了一个帮助文件,其中包含一堆相互调用的函数。

Helper.js

import React from 'react';
import SQLite from 'react-native-sqlite-storage';

let db;
let storage;

function runDemo() {
  loadAndQueryDB();
 //Suppose to return value assigned in queryPeopleSuccess but console logs 'undefined'
  console.log(storage);
  return storage;
}

//    Sends an update saying that Database was successfully opened
function openCB() {
  console.log("Success Opening DB");
}

//      Sends an update with error message and returns FALSE
function errorCB(err) {
  console.log("SQL Error: ", err);
  return false;
}

/** 2. Called when runDemo is called **/
/*   assigns variable 'db' to opened Database */
/*   Calls queryPeople(db) */
function loadAndQueryDB() {
  console.log("Opening Database...: ");
  
  db = SQLite.openDatabase({ name: "users.db", createFromLocation: 1}, openCB, errorCB);
  queryPeople(db);
}

/** 3. Called when loadAndQueryDB is called **/
/*    Get the DB and applies a SQL call that if successful will call queryPeopleSuccess*/
function queryPeople(db) {
  console.log("Executing employee query...");
  //Execute a database transaction.
  db.transaction((tx) => {
    tx.executeSql('SELECT * FROM users', [], queryPeopleSuccess, errorCB);
  });

}

function queryPeopleSuccess(tx, results) {
  var len = results.rows.length;
  let localArray = [];
  //Go through each item in dataset
  for (let i = 0; i < len; i++) {
    let row = results.rows.item(i);
    localArray.push(row);
  }

  storage = localArray;
}

export {
  runDemo,
}

我认为通过在函数外部分配“存储”将使它成为该文件中所有函数都可以访问的变量,而无需使其成为全局变量。此外,我有一个限制是我无法 return 从 queryPeopleSuccess 一直存储到 runDemo,因为这些函数中的函数不应该具有 return 值!

有人可以指出我如何在一个文件中拥有一个变量,该变量不需要位于 class 中,可以被该文件中的函数访问和编辑吗?

已编辑:为清晰起见和拼写错误进行了编辑。原来我的代码的问题是由于异步造成的!

taskFour 从未被调用过?您正在从 taskTwo 呼叫 taskThree

您的问题与 Javascript 中的 async 有关。

您当前的程序( script )是通过同步机制从上到下执行的,并且您没有为变量 storage 分配任何初始 value 。所以函数 runDemo with return 默认值 undefined.

要解决您的问题,您需要将 runDemo 转换为异步函数。

let storage;

async function runDemo() {
    await taskOne();
    //Suppose to return value assigned in taskFour but console logs 'undefined'
    console.log(storage);
    return storage;
}


function taskOne() {
    taskTwo();
}

function taskTwo() {
    taskFour();
}

let localArray = 20;

function taskFour() {

    storage = localArray;
    //Here storage is assigned properly and outputs the data I want
    console.log(storage);
}
runDemo()

你的问题是 runDemoqueryPeopleSuccess 甚至写入 storage 之前早就返回了。因此,您在它被写入之前阅读它,并且由于信息无法及时返回,您得到 undefined。基本上你有 this 问题。

您可以大大通过使用异步函数来简化您的代码:

import SQLite from 'react-native-sqlite-storage'

export async function runDemo () {
  console.log('Opening Database...: ')

  try {
    // This one is tricky, because it seems the library synchronously
    // returns the db instance, but before that it calls the success or
    // error callbacks (without passing the instance).
    const db = await new Promise((resolve, reject) => {
      const db = SQLite.openDatabase(
        { name: 'users.db', createFromLocation: 1 },
        // The trick here is that in the success case we wait for openDatabase
        // to return so that db will be assigned and we can resolve the promise
        // with it.
        () => setTimeout(() => resolve(db), 0),
        reject
      )
    })
    console.log('Success Opening DB')

    console.log('Executing employee query...')
    // Execute a database transaction.
    const results = await new Promise((resolve, reject) => {
      db.transaction(tx => {
        tx.executeSql(
          'SELECT * FROM users',
          [],
          (tx, results) => resolve(results),
          reject
        )
      })
    })

    const localArray = []
    // Go through each item in dataset
    for (let i = 0; i < results.rows.length; i++) {
      localArray.push(results.rows.item(i))
    }
    return localArray
  } catch (e) {
    console.log('SQL Error: ', e)
    return false
  }
}

然后你会在另一个异步函数中调用 runDemo 作为 console.log(await runDemo()),否则 runDemo().then(results => console.log(results), err => console.error(err))