在范围内通过回调函数传递数据

Posted

技术标签:

【中文标题】在范围内通过回调函数传递数据【英文标题】:Passing Data Through Call Back Functions When it Is In Scope 【发布时间】:2017-06-24 10:09:13 【问题描述】:

背景

我的问题是了解范围以及如何正确使用回调函数。在我尝试计划时,我似乎无法按顺序排列事件。我在阅读帖子并将它们与我当前的问题联系起来时遇到了麻烦。我想我真正不明白的是如何实现逻辑。

问题

我有一些情况导致我的应用程序出现问题。它们都围绕着我需要尚未在范围内的数据的情况。但是该函数已经有一个回调函数。

示例

此函数将数据插入数据库。

   updateProfile: function (req, res) 
    pool.getConnection(function (err, connection) 
        var email = req.body.email;
        var sql = 'INSERT INTO rw_users SET email = ?';
        var params = [email];

        connection.query(sql, params, function (err, results, fields) 
            if (err) 
                res.status(500).send();
                throw err;
            
            connection.release();
        );
    );
,

下一个函数需要刚刚创建的用户的 ID。

 createCustomerProfile: function (email, id) 
            merchant.createCustomerProfile(email, id, function callback(merchantRes)
                    pool.getConnection(function (err, connection) 
                var sql = 'UPDATE rw_user SET auth_customer_id = ? WHERE email = ?';
                var params = [merchantRes, email];
                connection.query(sql, params, function (err, results, fields) 
                    if (err) 
                        throw err;
                    
                    console.log('new customer created at authorize.net');
                );
            );
          );
        , 

在函数updateProfile() 中,我正在我的数据库中创建一个新用户。在第二个函数createCustomerProfile() 中,我需要在函数一中输入的新创建用户的 ID。

请告诉我一种处理此类功能的方法。我需要来自第一个进程的数据,以便我可以在第二个函数中使用它。这会变得最糟糕,因为当功能二完成时,它会在其 API 调用的响应中包含一个新的 customerID。该响应还需要进行另一个数据库查询以使用其 ID 更新该行。然后,一旦这两个函数完成后,我需要再次查询数据库以返回整行。

为了解决这个问题,

    在数据库中创建用户。 使用在函数 1 中创建的新用户的 ID 和电子邮件。在函数 2 中使用 authorize.net api 创建一个新的客户帐户 ID。 将来自 authorize.net API 响应的新客户 ID 插入在函数一中创建的新用户行中。 返回整行。

我的问题要明确。有什么可能的解决方案可以用来执行我的列表中的任务并清楚地执行它们以按顺序处理,以便我可以在每个响应存在于范围内时使用它?

【问题讨论】:

如果它们是两个不同的函数,则使用回调作为第三个参数来执行 createCustomerProfile 恐怕你的问题不清楚。您的问题是关于 javascript(如何在函数异步产生结果时将它们串在一起),还是关于 mysql 和插入后返回信息?另外:请不要讨论无关的细节。你的整个第一段和大约一半的文本是无关紧要的,只会妨碍人们阅读它并为你提供答案。 这里回答了 MySQL 问题(如果是这样的话):***.com/questions/31371079/… 对“nodejs mysql get last id”的简单搜索发现了它。更多关于搜索here。 对此我很抱歉。是的,我的问题是如何自信地把事件的顺序串起来。我最后列出的清单是我试图让它更清楚。我非常想了解这一点,所以我不会再回到这些问题上。您要我编辑问题吗?或者你明白我现在的意思了吗? 对于串在一起,请查看“promises”(很快就会出现新的async/await 语法,但现在是promises)。 【参考方案1】:

实现程序的最简单方法是使用嵌套回调,但这很容易变得混乱且难以维护您的代码。 我们可以使用 Promise 或 generators 以更优雅的方式来做到这一点。 首先,我们看一下下面的代码(简单的一个)。

     const test1= () => 
         return new Promise((resolve,reject)=>
              setTimeout(function() <-- async operation
                 resolve(10);
             )
         )
     

     const test2= (data) => 
         return new Promise((resolve,reject)=>
                    setTimeout(function() <-- async operation
                         resolve(data+20)
                    )
                )
     

     test1()
     .then(test2)
     .then((finalData)=>console.log(finalData));

这将为我们提供 30 的值。那么它是如何工作的。 test1 和 test2 都返回 promise 对象,该对象的方法名为 'then'。

   new Proimse((resolve,reject)=> async operation comes here , when the operation 
done successfully , we resolve it, otherwise reject , )

then方法期望一个函数,我们可以通过resolve函数传递参数。但是只需要一个参数,因此如果需要多个参数,则需要对象或数组。如果你能看懂上面的代码,让我们重构一下你的代码

     getConnection:function(req,res)
           return new Promise((resolve,reject)=>
                 pool.getConnection(function (err, connection) 
                        if(err) return reject(err);
                        resolve(connection,req,res);
             );
             )
     ,

     updateProfile:function(obj)
         const  connection,req,res  = obj;
         return new Promise((resolve,reject)=>
             var email = req.body.email;
             var sql = 'INSERT INTO rw_users SET email = ?';
             var params = [email];
             connection.query(sql, params, function (err, results, fields) 
                     if (err) return reject(err);
                     resolve(email,results,connection);
             );
         )
     ,

     createCustomerProfile: function (obj) 
                   const  email,results,connection  = obj;
                     return new Promise((resolve,reject)=>
                         merchant.createCustomerProfile(email, results.id, function callback(merchantRes)
                                 var sql = 'UPDATE rw_user SET auth_customer_id = ? WHERE email = ?';
                                 var params = [merchantRes, email];
                                 connection.query(sql, params, function (err, results, fields) 
                                         if (err) 
                                                 throw err;
                                         
                                         console.log('new customer created at authorize.net');
                                         connection.release();
                                 );
                     );
                     )
  

    yourModule.getConnection(req,res)
              .then(yourModule.updateProfile)
              .then(yourModule.createCustomerProfile)
              .catch((err)=>console.log(err))

现在您需要修改此代码,使其适用于您的模块。

【讨论】:

以上是关于在范围内通过回调函数传递数据的主要内容,如果未能解决你的问题,请参考以下文章

通过DOM元素数据集将回调传递给js

使用lambda函数进行向量排序,当不在同一范围内时如何传递变量来捕获组?

将额外变量传递给回调函数

Promise对象和回调函数,解决异步数据传递问题

单片机怎么用回调函数在不同文件之间传递数据

数据标准化和数据归一化有啥区别吗?