【问题标题】:Writing to an array in a higher scope, from within a query's anonymous function从查询的匿名函数中写入更高范围的数组
【发布时间】:2014-03-24 23:48:34
【问题描述】:

我需要从一个函数返回一个值,该函数从查询中获取其信息。我在将信息从查询的匿名函数传递到容器函数时遇到了一些问题。

我尝试在更高范围(容器函数)中创建一个数组,并让查询函数根据结果写入数组,但这似乎不起作用。我还尝试将数组传递给查询的匿名函数。这似乎也不起作用。


这是我的函数(在 Node 中执行):

function retrieveSales(connection,timeFrame) {

    var sales = new Array();

    connection.query('select * from sales_entries where date BETWEEN ? AND ?',
    timeFrame,

    function (err, rows, fields, sales) {

        if (err) return callback(new Error('Failed to connect'), null);

        connection.end();

        for (x = 0; x < rows.length; x++) {
            sales.push(rows[x]);
        }

    });

    console.log('Sales Returned: ' + JSON.stringify(sales, null, 4));

    return sales;

}

导致'cannot call method 'push' of undefined

我应该如何正确地写入sales 数组,以便可以使用retrieveSales() 返回它?

【问题讨论】:

  • connection.query()异步
  • 那么,我不能从中返回一个值?我应该如何获得允许我将返回值传递给另一个函数的结果?
  • 异步再次来袭...耶
  • 您的函数作为参数的sales 覆盖了您在更高范围内定义的sales
  • @jt0dd - 你可能想要一个承诺 - 节点支持它们,它会让你的代码看起来不错。 howtonode.org/promises

标签: javascript node.js function scope node-mysql


【解决方案1】:

您正在处理 JavaScript 的漂亮 asynchronous-ness-icity。您正试图从异步方法中返回。尝试复习异步编程的工作原理,它会让你的生活变得更加轻松;这不是很难,只是不同。看看这个代码示例,希望它能让你振作起来。

// use this as your callback to handle the results from connection.query()
function sales_cb(rows) {
  var sales = [];
  for (x = 0; x < rows.length; x++) {
    sales.push(rows[x]);
  }
  console.log('Sales Returned: ' + JSON.stringify(sales, null, 4));
}

function retrieveSales(connection, timeFrame) {
  // connection.query() is asynchronous - interact with it accordingly
  connection.query('select * from sales_entries where date BETWEEN ? AND ?', timeFrame,
    function (err, rows, fields, sales) {
      if (err) {
        callback(new Error('Failed to connect'), null);
      } else {
        // invoke sales_cb(sales) once the for loop is done
        sales_cb(rows);
      }
    });
}

如果这有帮助,请告诉我:)

【讨论】:

    【解决方案2】:

    使用:

    https://github.com/kriskowal/q

    以下是如何使用承诺:

    var q = require('q');
    
    
    function retrieveSales(connection,timeFrame) {
    
      var sales = new Array();
      var deferred = q.defer();
    
      connection.query('select * from sales_entries where date BETWEEN ? AND ?',
         timeFrame,
    
         function (err, rows, fields) {
    
         if (err) return callback(new Error('Failed to connect'), null);
    
         connection.end();
    
          for (x = 0; x < rows.length; x++) {
              sales.push(rows[x]);
          }
    
          deferred.resolve(sales);
      });
    
      deferred.then(function(salesback) {
        console.log('Sales Returned: ' + JSON.stringify(salesback, null, 4));
      }
    
      // added bonus -- the calling function can also use the promise
      return deferred;
    
    }
    

    更多信息:http://howtonode.org/promises

    【讨论】:

    • 虽然我选择了 *zmhr 的答案,因为它简单明了,可以解决问题并很好地回答我的问题,但我也对这种方法感兴趣。与使用所选答案中详述的方法相比,在我的情况下使用 Promise 有什么显着优势吗?
    • 简单来说,差别仅仅是因为偏好吗?
    • @jt0dd - 是的,就像编程中的大多数问题一样,解决方案有很多途径,有些更快,有些更优雅,有些更有趣,有些只是错误的。 zmhr 的回答很好——我的是性感的新技术。你选择:D
    • 你有 27.6k 代表。我要和 zmhr 一起去,因为失败者和懒惰的人摇滚!然而,说真的,在我完成第一个应用程序之后,这种花哨的新技术可能只是我要走的路。谢谢+1!
    • @jt0dd - 我刚刚重新阅读并意识到我没有在您的第一条评论中回答问题。对于这个例子来说,promise 闪耀的用例并不是很多,而是在你希望许多不同的函数在解析时触发的情况。您可以在我的示例中看到这一点,我登录到控制台并返回调用函数的承诺以触发。如果您没有这种用例,请使用 zmhr 的答案,因为它对于简单的情况更简单明了。
    猜你喜欢
    • 2011-07-13
    • 1970-01-01
    • 2011-02-13
    • 2015-09-20
    • 1970-01-01
    • 1970-01-01
    • 2011-10-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多