js匿名函数内部如何才能改变函数外部的局部变量值?

1、mysqljs的查询语句,最后一个参数是匿名函数,这个匿名函数为什么不能改变函数体外面的局部变量?如果要改变,如何做:
2、代码如下:

function checkExist(str) {
  let rt=0;
  if ((typeof(str)!='string' )||(str.length <= 1)) {rt=3 ;}
  let query = connection.query(
    "SELECT count(1) AS solution from taxlaw_chinatax_js where url like ? ",
    [str],
    (error, results, fields) => {
      if (error) throw error;
      let cou = results[0].solution;
      console.log(cou);
      if ( cou >= 1) {
        //console.log("检查数据已经采集过,忽略。");
        rt= 2;
      } else if (cou < 1) {
        //console.log("检查此条不存在,添加开始:" + str);
        rt= 1;
      }
    }
  );
  //console.log('检查数据库状态错误');
  //console.log(query.sql);
  return rt;
}

3、匿名函数(error, results, fields) => {}内部的rt值在超出函数的作用域之后,rt的值全部都是0。
实际上应该根据str的数据库查询结果,有的rt是2,有的rt是1,不应该统统是0.
也就是说,匿名函数改变不了外部变量rt的值。
想要改变,如何做?

4、试过直接在匿名函数内部直接返回rt值,也是无用的。代码如下:

function checkExist(str) {
  var rt=0;
  if ((typeof(str)!='string' )||(str.length <= 1)) {return 3 ;}
  connection.query(
    "SELECT count(1) AS solution from taxlaw_chinatax_js where url like ? ",
    [str],
    (error, results, fields) => {
      if (error) throw error;
      let cou = results[0].solution;
      console.log(cou);
      if ( cou >= 1) {
        //console.log("检查数据已经采集过,忽略。");
        return 2;
      } else if (cou < 1) {
        //console.log("检查此条不存在,添加开始:" + str);
        return 1;
      }
    }
  );
  //console.log('检查数据库状态错误');
  //console.log(query.sql);
  return 0;
}

这种情况下,返回的都是0。匿名函数只能返回一层,不能返回两层。

5、改成如下代码:

function checkExist(str) {
  var rt=0;
  if ((typeof(str)!='string' )||(str.length <= 1)) {return 3 ;}
  rt = connection.query(
    "SELECT count(1) AS solution from taxlaw_chinatax_js where url like ? ",
    [str],
    (error, results, fields) => {
      if (error) throw error;
      let cou = results[0].solution;
      console.log(cou);
      if ( cou >= 1) {
        //console.log("检查数据已经采集过,忽略。");
        return 2;
      } else if (cou < 1) {
        //console.log("检查此条不存在,添加开始:" + str);
        return 1;
      }
    }
  );
  //console.log('检查数据库状态错误');
  //console.log(query.sql);
  return rt;
}

返回的是个object,不是具体的数字。

如何做?

阅读 6.8k
2 个回答

数据库操作是异步操作,无法直接return结果的,
如果你能使用es7,可以用async, await来模拟同步

function checkExist(str) {
  return new Promise((resolve, reject) =>{
    let rt = 0;
    if ((typeof(str)!='string' )||(str.length <= 1)) {
        resolve(3);
        return;
    }
    connection.query(
      "SELECT count(1) AS solution from taxlaw_chinatax_js where url like ? ",
      [str],
      (error, results, fields) => {
        if (error) throw error;
        let cou = results[0].solution;
        console.log(cou);
        if ( cou >= 1) {
          resolve(2); //返回结果
        } else if (cou < 1) {
          resolve(1); //返回结果
        } else {
          reject(); //未知结果
        }
      }
    );
  });
} 

let process = async function() {
    try {
        let rt = await checkExist("str");
        console.log("rt:%s", rt);
    } catch(e) {
        console.log("unknow rt");
    }
}
process();

es5的话只能通过回调获得值:

function checkExist(str, callback) {
  var rt=0;
  if ((typeof(str)!='string' )||(str.length <= 1)) {
      callback(3);
      return;
  }
  connection.query(
    "SELECT count(1) AS solution from taxlaw_chinatax_js where url like ? ",
    [str],
    function (error, results, fields) {
      if (error) throw error;
      var cou = results[0].solution;
      console.log(cou);
      if ( cou >= 1) {
        callback(2);
      } else if (cou < 1) {
        callback(1);
      } else {
        callback("unknown");
      }
    }
  );
}

checkExist("str", function(rt) {
    console.log("rt:%s", rt);
}

操作数据库应该是一个异步的过程,使用es7的async、await结合promise试试。
把rt的值放在promise的resolve里面返回,然后再把返回值复制给外面的rt变量。

// 写文件
let _fileWrite = (file_name, write_content) => {
    return new Promise(function(resolve, reject){
         resolve({'result': 1});
    }
}

let fileString = await _fileWrite ;

之前项目里大概的代码,差不多的意思。把异步要返回的数据包裹在resolve里面,然后用await可以获取到resolve里的返回值。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题