js的回调函数还是很有学问的。
情景 nodejs循环读取数据库,回调函数回调的时候里面的index就早就被修改了。纠结了好久
错误代码:
UserPokemonService.getPokemonOfUserCarry = function (connection, userId, callback) { console.log('getPokemon'); var sql = 'SELECT * FROM user_pokemon WHERE user_id = \'' + userId + '\' and place > 0;'; var query = connection.query(sql,function(err,pokemonRows) { if(err) { console.log(this + err.code); } else { var len = pokemonRows.length; var todo = len; var pokemons = new Object(); console.log(len); if(len > 0) { //get move infomations for(var i = 0; i < len; i++) { var sqlMove = 'SELECT * FROM MOVES WHERE id = ' + pokemonRows[i]['move1_id'] + ' OR id = ' + pokemonRows[i]['move2_id'] + ' OR id = ' + pokemonRows[i]['move3_id'] + ' OR id = ' + pokemonRows[i]['move4_id']; console.log(sqlMove); console.log(pokemonRows[i]); pokemons[i] = new Object(); pokemons[i]['baseinfo'] = pokemonRows[i]; connection.query(sqlMove, function(err, moveRows) { console.log(i); if(err) { console.log(this + err.code); } else { //这里的i被修改了。 pokemons[i]['moves'] = moveRows; todo --; if(todo == 0) { callback(pokemons); } } }); } } else { callback(pokemons); } } }); }
回调函数里面的i被修改 所以就越界了。
TypeError: Cannot set property 'moves' of undefined
解决办法:
http://tech.richardrodger.com/2011/04/21/node-js-%E2%80%93-how-to-write-a-for-loop-with-callbacks/
用callback的最好别for 不然服务器压力大。
UserPokemonService.getPokemonOfUserCarry = function (connection, userId, callback) { console.log('getPokemon'); var sql = 'SELECT * FROM user_pokemon WHERE user_id = \'' + userId + '\' and place > 0;'; var query = connection.query(sql,function(err,pokemonRows) { if(err) { console.log(this + err.code); } else { var len = pokemonRows.length; var todo = len; console.log(len); if(len > 0) { //get move infomations loadMoveToPokemon(len - 1, pokemonRows, connection, callback); } else { callback(pokemons); } } }); } function loadMoveToPokemon(todo, userPokemonRows, connection, callback) { var sqlMove = 'SELECT * FROM MOVES WHERE id = ' + userPokemonRows[todo]['move1_id'] + ' OR id = ' + userPokemonRows[todo]['move2_id'] + ' OR id = ' + userPokemonRows[todo]['move3_id'] + ' OR id = ' + userPokemonRows[todo]['move4_id'];; connection.query(sqlMove, function(err, moveRows) { console.log(todo); if(err) { console.log(this + err.code); } else { userPokemonRows[todo]['moves'] = moveRows; if(todo == 0) { callback(userPokemonRows); } else { loadMoveToPokemon(todo-1, userPokemonRows, connection, callback); } } }); }