Javascript 使用Nodejs在Mysql中插入多个值并用响应通知用户

Javascript 使用Nodejs在Mysql中插入多个值并用响应通知用户,javascript,mysql,node.js,Javascript,Mysql,Node.js,我正在创建一个新的Web服务,其中我发送一个带有JSON的curl命令,JSON包含一个数组,如下所示 [{tempid:1,email:abc@123,address:asd},{tempid:2,email:abc@12345,address:asd45},{tempid:3,email:abc@1234,address:asd4}] 现在,当我在mysql表中传递并插入数组时,tempid只是向用户显示一个映射,映射到数据库中生成的联系人id,tempid:1现在被插入,在数据库中它有c

我正在创建一个新的Web服务,其中我发送一个带有JSON的curl命令,JSON包含一个数组,如下所示

[{tempid:1,email:abc@123,address:asd},{tempid:2,email:abc@12345,address:asd45},{tempid:3,email:abc@1234,address:asd4}]
现在,当我在mysql表中传递并插入数组时,tempid只是向用户显示一个映射,映射到数据库中生成的联系人id,tempid:1现在被插入,在数据库中它有cid 120,就像tempid2和tempid3一样

但是,当我试图向客户机显示更新的值时,它只显示一个值,最后一次更改,而不是整个更新的数组。这是因为connection.query函数的异步性质,所以我需要这方面的帮助,这是我的Web服务

联系人添加Web服务-->

for(var i=0;i<=request.body.contact.length-1;i++)
            {
             if(request.body.contact[i].tempid)
                { var ardata=new Array();
                    var o=request.body.contact[i];
                    pair=Object.keys(o).map(function(a){ return [a, o[a]] });
                    AM.addcontact(pair,request.session.user,request.body.contact.length,function(e,o){
                        if(!o)
                        {
                             response.send('something went wrong'+e);

                        }
                        else
                        {
                           //response.send(o);
                        }

                    });


                }
    }
//ContactSync-addcontact module for database 
exports.addcontact=function (arr,email,addnum,callback)
{ 
  var counter=0;
  var uid;
  var data=new Array();
  var showinsert=new Array();
  var values=new Array();
  var datatable=new Array();
  var inserting=new Array();

  var tempid=0;
   connection.query('SELECT UID FROM user where email1="'+email.email+'"',function(err,rows,fields){
    if(err)
    {
     throw err;
    }
    else
    {
    if(rows[0]!=undefined)
    {
     uid=rows[0]['UID'];
    }
    else
    {
    uid="no id in database";
    }
    }
    });// get the UID of the inserting user

    // make array of user provided data
    for(var j=0;j<=arr.length-1;j++)
    {
     if(arr[j][0]!='tempid')
     {
      data.push(arr[j][0]);
     }
     else
     {
      tempid=arr[j][1];
     }
    }

    connection.query('SELECT column_name FROM information_schema.columns where table_schema="webservice" AND table_name="usercontacts"',function(err,rows,fields){
    if(err)
    {
     throw err;
    }
    else
    {

    for(var i=0;i<=rows.length-1;i++)
    {
      datatable.push(rows[i]['column_name']);

    }
    }
       for(var k=0;k<=datatable.length-1;k++)
        {
          if(inArray(data[k],datatable))
          {
            inserting.push(data[k]);
          }
        }
        if(inserting.length>0)
        {


            for(var z=0;z<=arr.length-1;z++)
            {
              if(inArray(arr[z][0],inserting))
               { 

                 values.push('"'+arr[z][1]+'"');

               }
            }


            // Insert tempid values and data in the usercontacts table with inserting and values

            connection.query('INSERT INTO usercontacts (cid,uid,'+inserting+') VALUES("","'+uid+'",'+values+')',function(err,rows,fields){
            if(err)
            {
            throw err;
            }
            else
            {  
                connection.query('SELECT * FROM usercontacts WHERE uid="'+uid+'" ORDER BY cid DESC LIMIT 0,'+addnum+'',function(err,rows,fields){
                if(err)
                {
                    throw err;
                }
                else

                {   showinsert.push('temp-id: '+tempid+',cid:'+rows[0].cid+',uid:'+uid);
                    //for(var i=0;i<=inserting.length-1;i++)
                    forEach(inserting,function(row,index)
                    {
                      showinsert.push(inserting[index]+":"+values[index]);
                      counter+=1;
                    });

                    callback(null,showinsert);

                }

                });
            }

            });

            //insertion finished 


        }
        else
        {
          callback("Please Provide atleast one field to enter with tempid");
        }

  });


}
for(var i=0;i

//ContactSync为数据库添加联系人模块
exports.addcontact=函数(arr、电子邮件、addnum、回调)
{ 
var计数器=0;
变量uid;
var data=新数组();
var showinsert=新数组();
var值=新数组();
var datatable=新数组();
插入变量=新数组();
var-tempid=0;
connection.query('SELECT UID FROM user where email1=“”+email.email+””,函数(err、行、字段){
如果(错误)
{
犯错误;
}
其他的
{
如果(行[0]!=未定义)
{
uid=行[0]['uid'];
}
其他的
{
uid=“数据库中没有id”;
}
}
});//获取插入用户的UID
//生成用户提供数据的数组

对于(var j=0;j我不确定具体的问题是什么,但您共享的代码中存在一些问题,这些问题迟早会困扰您。其中之一可能会导致您的问题

比赛条件

如果查询
SELECT UID FROM user where email1=
出于任何原因所花费的时间超过
SELECT column\u name FROM information\u schema。columns
就在它的下方,那么变量
uuid
将没有值,逻辑将失败。请记住,这些调用是非阻塞的,因此不能依赖于一个变量在另一个之前,除非它们是嵌套的或使用另一个流控制机制(正如@Tracker指出的,这种机制很流行)

捕捉边缘案例

在下一行中,您将为
uid
变量指定一个字符串值,然后继续使用该变量,即使它现在包含错误消息

    uid="no id in database";
这样做意味着您的代码以后将无法做出反应。请使用不同的变量,保留
uid=undefined
,或者立即返回带有错误的回调,例如

    return callback(new Error("user not found"));
报告错误

除非您想终止进程,否则不要在节点中抛出错误,例如服务器启动期间的依赖性问题。它不像Java那样工作,异步错误不会被try/catch捕获,并且会终止进程或使您处于难以解释的状态。相反,将error对象作为回调的第一个参数,并将其返回immed最近,像这样:

    if ( err ) return callback(err);
    connection.query('SELECT UID FROM user where email1=?', [email.email], ...
然后,在客户端代码中,您可以始终检查第一个参数,以查看是否存在问题

安全问题

正如@Tracker所提到的,永远不要这样做:

    connection.query('SELECT UID FROM user where email1="'+email.email+'"', ...
如果变量的值以
“drop table user;”
或类似形式传递,则您会遇到麻烦。相反,您可以使用节点mysql的内置转义,如下所示:

    if ( err ) return callback(err);
    connection.query('SELECT UID FROM user where email1=?', [email.email], ...
白名单

您正在查询
信息\u架构。列
以检测哪些字段是有效的,然后将它们插入
用户联系人
。这是一个聪明的技巧,但将3个查询过程增加到4个查询,并会问到是否有用户不应在其中插入数据的字段。使用列白名单可能看起来很简单ike需要维护更多的代码,但实际上比动态匹配列所需的所有代码都要简单

阵列

我没有看到函数
inArray()
的源代码,但它看起来与
Array.prototype.indexOf()
的功能相同,因此使用它可能更好

    if ( datatable.indexOf(data[k]) > -1 ) inserting.push(data[k]);

您可以删除的每一行自定义代码都是一行您不必维护的代码。

有三个争议点…首先,建议将您的检查/插入包装到一个SQL语句中,该语句返回与电子邮件地址匹配的给定用户的现有uid或新uid…第二,建议参数化查询,而不是字符串连接…第三,查看
npm install async--save
async模块将提供对集合进行迭代的方法,并返回完整的结果集或错误。第四,您应该在整个过程中使用事务,以便它可以作为一个整体成功或失败。您好,感谢您的评论,我已经粘贴了我的new更新了服务端的代码,我正在运行foreach,但变量ardata在响应时仍然为空/无,请帮助假设ardata是数组
[]
尝试ardata.push(值)ardata是一个简单的变量,我已经尝试过了,事实上我刚刚使用了Async.Seriesh这里是当前的代码-->非常感谢您宝贵的时间和宝贵的教训,从现在起我将永远记住这一点。再次感谢。我再次从头做起,这次我使用了查询嵌套,这是一个不好的做法吗?嵌套很好,但可以我的建议是先使用嵌套,直到你对这种类型的代码感到满意,然后再研究
async
。我个人并不喜欢承诺,但这也是一种选择。另外一个建议是,如果你给匿名函数起一个名字,例如
doSomething(函数myUniquelyNamedCallback(){…})
,则名称将显示在堆栈跟踪中,而不是“匿名函数”。另一个提示…使用节点检查器向重要点添加断点,您将能够一步一步地浏览应用程序,同时查看变量的值