我一生不能正确选择吗?我可能有错误的循环,所以如果是这样,请建议:
function(data, callback){
data.champNames = {};
for(var c in data.champId){
val = data.champId[c];
var surl = 'https://global.api.pvp.net/api/lol/static-data/euw/v1.2/champion/'+ [val] + '?api_key=' + api_key;
request(surl, function(err, response, body){
if(!err && response.statusCode == 200){
var json = JSON.parse(body);
//data.champNames.push(json[val].name);
console.log(json);
} else {
console.log('Error in Champ Name');
}
})
console.log(val);
} console.log(data);
}
data.champnames.push(json [val] .name)将不起作用,json在控制台中以下面的形式返回:
:{ id: 1, key: 'Annie', name: 'Annie', title: 'the Dark Child' }
{ id: 76,
key: 'Nidalee',
name: 'Nidalee',
title: 'the Bestial Huntress' }
{ id: 15,
key: 'Sivir',
name: 'Sivir',
title: 'the Battle Mistress' }
{ id: 103,
key: 'Ahri',
name: 'Ahri',
title: 'the Nine-Tailed Fox' }
数据是在异步瀑布中使用的全局变量。
Champid已经在数组中,返回为:
champId: [ 22, 236, 76, 21, 36, 133, 24, 103, 81, 79, 45, 15, 1, 0 ],
data.champNames={}
是您的情况下的字典。要使用push
方法,您需要使用array
。尝试以下操作:
data.champNames = [];
或,如果您想使用字典,请使用以下方式:
data.champNames["key"]=value;
更新答案:
一种方法是使用立即启动的函数表达式
for(var c in data.champId){
val = data.champId[c];
var surl = 'https://global.api.pvp.net/api/lol/static-data/euw/v1.2/champion/'+ [val] + '?api_key=' + api_key;
(function(val){
request(surl, function(err, response, body){
if(!err && response.statusCode == 200){
var json = JSON.parse(body);
//data.champNames.push(json[val].name);
console.log(json);
} else {
console.log('Error in Champ Name');
}
})(val);
console.log(val);
}
另一个解决方案是使用let
关键字。
es6为这种确切情况提供了LET关键字。代替 使用闭合,我们只能使用让设置循环范围变量。
请尝试:
for(let c in data.champId){
let val = data.champId[c];
var surl = 'https://global.api.pvp.net/api/lol/static-data/euw/v1.2/champion/'+ [val] + '?api_key=' + api_key;
request(surl, function(err, response, body){
if(!err && response.statusCode == 200){
var json = JSON.parse(body);
//data.champNames.push(json[val].name);
console.log(json);
} else {
console.log('Error in Champ Name');
}
})
}
访问对象似乎是一个问题,更大的问题实际上是您处理数据的方式。您正在执行同步环(for...in
)内的异步操作(request(...)
)。由于JavaScript的工作方式,这意味着循环将在执行任何request
回调之前先完成。
您的代码中的问题已在其他问题和资源中得到了广泛涵盖,因此我强烈建议您在执行其他任何操作之前阅读以下内容:
- 并发模型和事件循环
- javaScript闭合循环 - 简单实践示例
- 为什么在函数内部修改它之后,为什么我的变量不变? - 异步代码参考
- 如何从异步呼叫中返回响应?
为了解决您的特定问题,您应该研究 Promises 。我们将为data.champId
数组中的每个条目创建一个新的承诺。承诺基本上是A 未来价值的占位符。如果有错误,承诺可以可以解决被拒绝。在这里,每个诺言都是通过request
收到的响应的占位符,这是一个异步过程。特别是,这些诺言中的每一个都将解决响应对象的name
。诸如Promise.all
之类的助手方法允许我们一旦解决多个承诺就可以执行动作。
function fetchNames(data) {
// Promise.all returns a new promise that resolves when all promises passed to it
// are resolved
return Promise.all(data.champId.map(function(id) {
var surl = 'https://global.api.pvp.net/api/lol/static-data/euw/v1.2/champion/'+ id + '?api_key=' + api_key;
// Create a new promise for each entry in data.champId
return new Promise(function(resolve, reject) {
request(surl, function(err, response, body){
if (!err && response.statusCode == 200){
var result = JSON.parse(body);
resolve(result.name); // the response is an object with a property name
} else {
reject('Unable to load entry "' + id + '"');
}
});
});
}
fetchNames({champId: [ 22, 236, 76, 21, 36, 133, 24, 103, 81, 79, 45, 15, 1, 0 ]})
.then(function(names) {
console.log(names);
})
.catch(function(error) {
// An error occured
});
您正在尝试在一个对象上进行推动:您声明为 data.champNames = {}
,但是对于推动,您需要一个数组data.champNames = [];
)。
阅读代码,我可以假设您正在尝试读取JSON数组的VAL-TAL元素,而不是具有ID == Val的JSON元素。如果您想获得具有ID == Val的元素的名称,则必须在JSON对象内进行搜索。