处理在nodejs承诺链中传入的参数

handling passed in parameters in nodejs promise chain

我是 Nodejs 和 javascript developmnet 的新手。我最近遇到了 promises,我想知道如何解决我面临的问题。

这是我的代码:

  for (let j = 0; j < expired_vals.length; j++) {

    var data = {
      'customer-id': expired_vals[j].customer,
      'sound-id': expired_vals[j].id
    };  
    console.log(data)

    getDatabaseTemporaryURL(data).then(function(url) {
      console.log(data)
      if(url) {
       //do stuff with url
      }
    });
 }

在上面的代码中第一个console.log returns数据的正确值,

{ 'customer-id': 1, 'sound-id': 245 }
{ 'customer-id': 1, 'sound-id': 246 }
{ 'customer-id': 1, 'sound-id': 247 }
{ 'customer-id': 1, 'sound-id': 248 }
{ 'customer-id': 1, 'sound-id': 249 }

在第二个日志中我只重复了最后一个值,

{ 'customer-id': 1, 'sound-id': 249 }
{ 'customer-id': 1, 'sound-id': 249 }
{ 'customer-id': 1, 'sound-id': 249 }
{ 'customer-id': 1, 'sound-id': 249 }
{ 'customer-id': 1, 'sound-id': 249 }

我知道这是我的承诺链的问题,因为 getDatabaseTemporaryURL 是一个承诺函数。

function getTemporaryURL({ data }) {

  const customer_id = data['customer-id'];
  const sound_id = data['sound-id'];
  
  return new Promise((resolve, reject) => {
    //get presigned url
    //do stuff and resolve
  });

}

如何修改我的代码,以便我可以在 getDatabaseTemporaryURL 的 .then 中访问每个正确的数据迭代?或者我应该转向 async/await 情况?

告诉我!任何帮助将不胜感激!

有两件事导致了这个:

  1. var 创建函数作用域变量
  2. .then() 在整个循环完成后被调用,所有你的 .then() 处理程序将只记录你的 data 变量的最后一个值。

这里有更多细节。当您使用:

var data = {...};

这将创建一个具有函数作用域的变量。循环的后续迭代只是分配给该变量,它们不会创建新变量。因此,循环的所有迭代都使用相同的变量。

相当于:

  var data;
  for (let j = 0; j < expired_vals.length; j++) {

    data = {
      'customer-id': expired_vals[j].customer,
      'sound-id': expired_vals[j].id
    };  
    console.log(data)

    getDatabaseTemporaryURL(data).then(function(url) {
      console.log(data)
      if(url) {
       //do stuff with url
      }
    });
 }

然后,由于 .then() 处理程序总是在当前 Javascript 上下文完成执行后异步调用,这意味着您的 for 循环将在您的任何 [=14] 之前完成执行=] 处理程序被调用。因此,当您在 .then() 处理程序中 console.log(data) 时,您将看到的只是您在循环中分配给 data 的最后一个值——您在 data 的最后一次迭代中分配的值=18=]循环。


如果您希望每个 .then() 为自己的 for 循环迭代记录 data 变量的值,则使用 let 而不是 var.

  for (let j = 0; j < expired_vals.length; j++) {

    let data = {
      'customer-id': expired_vals[j].customer,
      'sound-id': expired_vals[j].id
    };  
    console.log(data)

    getDatabaseTemporaryURL(data).then(function(url) {
      console.log(data)
      if(url) {
       //do stuff with url
      }
    });
 }

这将为循环的每次迭代创建一个单独的 data 变量。 let 给出变量块作用域,因此 data 变量具有循环作用域,而不是函数作用域。

仅供参考,您应该永远不要再使用 var。使用 letconst。如果你真的想要一个函数范围的变量,你总是可以在你的函数的顶部放置一个 let 定义。否则,您可以使用 constlet 更精确地控制变量的范围,这总是一件好事。