我有一个数据库中的用户列表。在注册到db时,他们最初被给予了access_token,但是当它到期时,我需要通过refresh_token创建一个新的access_token,它也已经在数据库中保存了对用户。
我需要向端点发出POST请求以访问获取新的访问令牌。
我试图遍历数据库中的每一行并以这种方式获得新的access_token。当有一个用户时它可以正常工作,但是当users
数组中有多个用户时,每个user
都是相同的,即数据库表中的最后一个用户。我猜这个请求还没有完成,它正在尝试发送新的请求或类似的东西。
有谁知道怎么解决这个问题?
app.get('/get-users', function (req, res) {
connection.query('SELECT * from users', function(err, rows, fields) {
if(err) console.log(err);
for(var i = 0; i < rows.length; i++) {
name = rows[i].name;
userId = rows[i].userId;
console.log(userId);// this gives the correct userid
var authOptions = {
url: url,
headers: {
'Authorization': 'Basic ' + (new Buffer(client_id + ':' + client_secret).toString('base64'))
},
form: {
grant_type: 'refresh_token',
refresh_token: refresh_token
},
json: true
};
request.post(authOptions, function(error, response, body) {
if (!error && response.statusCode === 200) {
var access_token = body.access_token;
users.push({name: name, userId: userId, accessToken: access_token});
console.log(userId)//gives last entry in db
}
});
setTimeout(function () {
console.log(users)
}, 3000)
}
});
res.send('getting here');
})
答案 0 :(得分:0)
你的问题是:
for(var i = 0; i < rows.length; i++) {
name = rows[i].name;
userId = rows[i].userId;
// ...
request.post(authOptions, function(error, response, body) {
// you're using name and userId here
});
// and also you use users here:
console.log(users)
}
现在,问题是在循环迭代的全部完成之前,不会调用任何回调(即使是第一次迭代)。
首先,console.log(users)
总是会得到users
的价值,无论 之前发生了什么users.push()
。
此外,对于每次回调,name
和userId
的值将相同 - 无论您for
循环的最后一次迭代后是什么。
您的name
和userId
似乎是全局变量,或者它们是在某些外部范围内定义的。您需要做的是使用let
在本地定义它们,以便它们为每个循环迭代获得新的绑定。
请参阅一个简单示例来演示此处发生的事情:
for (var i = 0; i < 4; i++) {
x = 'Number ' + i;
setTimeout(function () {
console.log(x);
}, 500*i);
}
这不好,因为x
是一个全局变量。现在使用var
:
for (var i = 0; i < 4; i++) {
var x = 'Number ' + i;
setTimeout(function () {
console.log(x);
}, 500*i);
}
仍然不好,因为每次迭代共享x
只有一个绑定。现在使用let
:
for (var i = 0; i < 4; i++) {
let x = 'Number ' + i;
setTimeout(function () {
console.log(x);
}, 500*i);
}
它起作用,因为每次迭代都会获得一个新的绑定。
另一件事是确保您知道每个request.post
何时结束,以便您可以在合适的时间发送回复。
您可以使用async来帮助您。您可以使用Bluebird或Q等承诺和库来帮助您。但你也可以做一个简单的伎俩。如果你想知道你在上面展示的例子的最后一个回调中,你可以计算这样的调用:
let current = 0, last = 0;
for (let i = 0; i < 4; i++) {
let x = 'Number ' + i;
setTimeout(function () {
if (++current === last) console.log('Last callback:');
console.log(x);
}, 500*i);
last++;
}
这可能不是处理复杂情况的最佳方法,但它演示了正在发生的事情:last
变量在每次迭代时都会递增,而回调只会在那时进行注册。然后回调开始一个接一个地触发,你可以在每次触发一个回调时增加current
变量,并比较它是否是最后一个。
现在,一般建议:每次使用let
(或const
)代替var
。它的工作方式更加直观。当然,如果你知道自己在做什么,可以使用var
,但如果有疑问则使用let
。