Nodejs For 循环里执行conn.query 出错时不用throw怎么跳出For循环。

Nodejs For 循环里执行conn.query 出错时不用throw怎么跳出For循环。

function uploadInfos(recJSON,conn,callback){
userId=recJSON.userIn
for (var i in recJSON.Infos){
var error;
conn.query(‘INSERT INTO log SET data=?’, recJSON.Infos[i].data, function(err, result) {
if (err) {callback(err,null,userId); }//这里我用的callback回调,不用throw因为callback里还有记录日志的操作。
});
}
}

请问怎么跳出for循环,或者直接return跳出函数,谢谢!


10 回复

在 Node.js 中使用 conn.query 进行数据库操作时,由于这些操作是异步的,因此在 for 循环中执行这些操作时,你不能简单地使用 breakreturn 来跳出循环或函数。你需要确保所有查询都完成后再进行下一步操作。

为了实现这一点,你可以使用 Promise 和 async/await 语法来管理异步操作,并确保在所有查询完成后才调用回调函数。以下是一个改进后的示例:

function uploadInfos(recJSON, conn, callback) {
    const userId = recJSON.userId; // 确保变量名正确

    const queries = recJSON.Infos.map(info => {
        return new Promise((resolve, reject) => {
            conn.query('INSERT INTO log SET data=?', [info.data], (err, result) => {
                if (err) {
                    reject(err);
                } else {
                    resolve(result);
                }
            });
        });
    });

    Promise.all(queries)
        .then(() => {
            callback(null, 'All inserts successful', userId);
        })
        .catch(err => {
            callback(err, null, userId);
        });
}

解释:

  1. 映射查询:我们首先将每个插入操作转换为一个 Promise 对象。这样,我们可以等待所有 Promise 完成。
  2. Promise.allPromise.all 接受一个 Promise 数组,并返回一个新的 Promise。这个新的 Promise 在所有输入的 Promise 都成功完成时才会成功,否则会在第一个失败的 Promise 失败时失败。
  3. 错误处理:如果任何一个查询失败,Promise.all.catch 方法会被触发,从而调用回调函数并传递错误信息。
  4. 成功处理:如果所有查询都成功完成,则调用回调函数并传递成功消息。

通过这种方式,你可以确保所有的数据库插入操作都完成后再进行下一步操作,而不会过早地跳出循环或函数。


如果是数组循环的话,可以当出现err时,让i=数组.length。如果是对象的话,可以if(err) break;

对了,还有个方法就是goto语句了,可以这样 function uploadInfos(recJSON,conn,callback){ userId=recJSON.userIn lookHere: for (var i in recJSON.Infos){ var error; conn.query(‘INSERT INTO log SET data=?’, recJSON.Infos[i].data, function(err, result) { if (err) { break lookHere; }//这里就可以跳出了 }); } }

谢谢,我试试看

不能一次插入多条数据? conn.query(“insert ……; insert ……”);

我怎么觉得 for 循环已经执行完了,因为conn.query是异步操作。

对啊。。我也觉得

可以的,我后来才知道insert into table (NoteId,NoteUserId) values (xxx,xxxx),(xxxx,xxxx) 就可以插入多条了

是执行完了,我前面的理解又问题,后来问了人,用递归解决了这个问题

在这个问题中,你需要在 conn.query 执行出错时不使用 throw 来跳出循环或返回函数。可以利用回调函数来处理错误,并且在遇到错误时不再继续执行循环。

你可以使用一个标志变量来跟踪是否发生了错误,并且在外层定义一个函数来递归调用 conn.query 直到完成所有操作或遇到错误。以下是改进后的代码示例:

function uploadInfos(recJSON, conn, callback) {
  let userId = recJSON.userId;
  let infos = recJSON.infos;
  let index = 0;

  function queryNext() {
    if (index >= infos.length) {
      return callback(null, 'All records processed successfully', userId);
    }

    conn.query('INSERT INTO log SET data=?', [infos[index].data], function (err, result) {
      if (err) {
        return callback(err, null, userId);
      }
      index++;
      queryNext();
    });
  }

  queryNext();
}

解释

  1. 定义变量:初始化 userId, infos 数组以及索引 index
  2. 定义递归函数 queryNext():该函数用于递归地执行查询。
  3. 检查结束条件:如果 index 大于等于 infos.length,表示所有记录已经处理完毕,调用 callback 并返回成功信息。
  4. 执行查询:使用当前索引的记录执行插入操作。
  5. 错误处理:如果发生错误,直接调用 callback 返回错误信息。
  6. 递归调用:如果插入成功,增加索引并递归调用 queryNext(),继续处理下一个记录。

这种方法确保了即使发生错误也能跳出循环,并正确处理错误情况。

回到顶部