J'exécute une fonction qui doit pousser 16 objets dans la position i d'un tableau multidimensionnel. Je suis capable de pousser toutes les données dans var = videoData utilisant videoData.push(videoItem) mais je dois me retrouver avec un tableau multidimensionnel où chaque tableau imbriqué contient 16 objets.
var videoData = [[vid01, vid02....vid16], [vid01, vid02... vid16]]
Je m'attends à finir avec ...
//variables
videoData = [],
countries = ["GB", "ES", "PT", "VN", "ID"],
tags = ["?tags=english", "?tags=spanish", "?tags=portugues", "?tags=vietnam", "?tags=indonesia"]
//function
function runTask(){
for(var i = 0; i < countries.length; i++){
axios({
method: "get",
url: api_url + tags[i],
headers: {
"Content-Type": "application/json"
},
})
.then(function(response) {
var sixteenVideos = response.data
for(var x = 0; x < 16; x++){
var videoItem = {
"keys": {
video: "vid" + [x+1]
},
"values": {
url: sixteenVideos[x].slug,
thumb: sixteenVideos[x].image,
title: sixteenVideos[x].title,
desc: sixteenVideos[x].description
}
}
videoData[i].push([videoItem]);
}
console.log(videoData);
}).catch(function(error) {
console.log(error);
});
}
}
4 Réponses :
Vous souhaitez utiliser une boucle similaire à celle-ci pour créer votre tableau multidimensionnel
function runTask() {
var videoData = [];
for (var i = 0; i < 6; i++) {
var country = "Country -" + i;
var countryArray = [];
for (var x = 0; x < 16; x++) {
var videoItem = country + ", Video -" + x;
countryArray.push(videoItem);
}
videoData.push(countryArray);
}
}
For boucle For fonctionne de manière synchrone, lors de l'exécution d'opérations asynchrones dans la boucle for , au moment où les promesses sont résolues for boucle terminée, son exécution. Ainsi, la valeur de i aura la valeur de la dernière itération de boucle dans chaque promesse résolue.
Je ne pense pas que la boucle for soit vraiment nécessaire ici, il peut être plus simple de créer une fonction qui prend une balise et renvoie une promesse qui se résout en un tableau de 16 éléments, cela peut ressembler à ceci:
var videoData = [];
var countries = ["GB", "ES", "PT", "VN", "ID"];
var tags = ["?tags=english", "?tags=spanish", "?tags=portugues", "?tags=vietnam", "?tags=indonesia"];
var tasks = tags.map(runTask);
Promise.all(tasks).then(result => {
console.log(result)
});
function runTask(tag) {
return axios({
method: "get",
url: api_url + tag,
headers: {
"Content-Type": "application/json"
},
}).then((response) =>
response.data
.slice(0, 16)
.map((video, index) => ({
"keys": {
video: "vid" + [index + 1]
},
"values": {
url: video.slug,
thumb: video.image,
title: video.title,
desc: video.description
}
}))
).catch(err => {
console.log(err)
})
}
Il y a beaucoup de problèmes avec votre code actuel. Je vais partir de zéro dans l'espoir que vous puissiez voir une meilleure façon d'aborder cela. Premièrement, axios a de nombreuses fonctionnalités de bas niveau que vous ne devriez pas vous inquiéter à chaque fois que vous récupérez json. Commencez par quelque chose comme fetchJson -
const apiUrl =
"https://my.api/"
const requests =
[ { country: "GB", tags: "?tags=english" }
, { country: "ES", tags: "?tags=spanish" }
, { country: "PT", tags: "?tags=portugues" }
, { country: "VN", tags: "?tags=vietnam" }
, { country: "ID", tags: "?tags=indonesia" }
]
const fetchJson = (url = "") =>
axios
( { method: "get"
, url
, headers: { "Content-Type": "application/json" }
}
)
.then(res => res.data)
const fetchVideos = ({ country = "", tag = "" }) =>
fetchJson(apiUrl + tag)
.then(apiVideos => apiVideos.map(videoFromApi))
.then(videos => ({ country, videos }))
const videoFromApi =
( { slug = ""
, image = ""
, title = ""
, description = ""
}
, id = 0
) =>
Object.assign
( { keys: { video: `vid${id + 1}` } }
, { values:
{ url: slug
, thumb: image
, title: title
, desc: description
}
}
)
// mocks
const axios = async (req = {}) =>
({ data: randomVideos(4) })
const randomVideos = (n = 0) =>
Array.from(Array(n), randomVideo)
const randomVideo = (_, id) =>
( { url: `videourl/${id}`
, image: `images/v${id}.jpg`
, title: `Video: ${id}`
, description: `This is video ${1}.`
}
)
// run demo
Promise
.all(requests.map(fetchVideos))
.then(console.log, console.error)
// [ { country: "GB", videos: [ v1, v2, v3, ... ] }
// , { country: "ES", videos: [ v1, v2, v3, ... ] }
// , { country: "PT", videos: [ v1, v2, v3, ... ] }
// , { country: "VN", videos: [ v1, v2, v3, ... ] }
// , { country: "IN", videos: [ v1, v2, v3, ... ] }
// ] Maintenant, lorsque nous écrivons fetchVideos , nous pouvons compter sur fetchJson et sauter directement dans ce que nous devons faire avec la réponse analysée -
const requests =
[ { country: "GB", tags: "?tags=english" }
, { country: "ES", tags: "?tags=spanish" }
, { country: "PT", tags: "?tags=portugues" }
, { country: "VN", tags: "?tags=vietnam" }
, { country: "ID", tags: "?tags=indonesia" }
]
Promise
.all(requests.map(fetchVideos)) // fetchVideos for each request
.then(console.log, console.error) // then log the output, or error if incurred
// [ { country: "GB", videos: [ v1, v2, v3, ... ] }
// , { country: "ES", videos: [ v1, v2, v3, ... ] }
// , { country: "PT", videos: [ v1, v2, v3, ... ] }
// , { country: "VN", videos: [ v1, v2, v3, ... ] }
// , { country: "IN", videos: [ v1, v2, v3, ... ] }
// ]
Au lieu de s'appuyer sur des tableaux séparés de countries et de tags , fetchVideo prend une entrée d' objet telle que -
const videoFromApi =
( { slug = ""
, image = ""
, title = ""
, description = ""
}
, id = 0
) =>
Object.assign
( { keys: { video: `vid${id + 1}` } }
, { values:
{ url: slug
, thumb: image
, title: title
, desc: description
}
}
)
Et il produira un objet tel que -
// { country: "GB", videos: [ v1, v2, v3, ... ] }
Cela évite d'avoir à utiliser des index bruts pour lier des valeurs entre elles. Et nous avons gardé fetchVideos haut niveau en fonction d'une autre fonction videoFromApi . Cette fonction convertira les données de réponse vidéo de l'API dans la forme souhaitée pour notre application -
fetchVideos({ country: "GB", tag: "?tags=english" })
.then(console.log, console.error)
Maintenant, pour lier tout cela, nous définissons un tableau de requests et utilisons Promise.all pour fetchVideos des fetchVideos pour chaque requête. NB, cela nous permet de savoir précisément quand toutes les récupérations d'API sont terminées afin que notre programme puisse passer à l'étape suivante -
const apiUrl =
"https://my.api/"
const fetchVideos = ({ country = "", tag = "" }) =>
fetchJson(apiUrl + tag)
.then(apiVideos => apiVideos.map(videoFromApi)) // convert each video
.then(videos => ({ country, videos })) // build response
Pour voir une démo fonctionnelle, développez l'extrait ci-dessous et exécutez-le. axios a été randomVideos avec randomVideos afin que nous puissions simuler une requête d'API -
const fetchJson = (url = "") =>
axios
( { method: "get"
, url
, headers: { "Content-Type": "application/json" }
}
)
.then(res => res.data)
Eh bien, vous ne pouvez pas faire cela "videoData[i].push" car la position sur le tableau n'existe pas. Vous pouvez résoudre ce problème en utilisant un tableau auxiliaire comme celui-ci:
for(var x = 0; x < 16; x++){
var videoItem = {
"keys": {
video: "vid" + [x+1]
},
"values": {
url: sixteenVideos[x].slug,
thumb: sixteenVideos[x].image,
title: sixteenVideos[x].title,
desc: sixteenVideos[x].description
}
}
videoDataAux.push([videoItem]);
}
videoData[i]=videoDataAux
et que:
videoData = [] videoDataAux = []
Quelle est la sortie de courant? Est-ce quelque chose comme
[vid01,[vid01...]...]?Non, c'est des erreurs pour le moment. Il montre
TypeError: Cannot read property 'push' of undefinedCela signifie que quel que soit le système
videoitem, il n'est pas défini. Êtes-vous sûr de recevoir correctement les données? Qu'est-ce que vousconsole.log(response);? Vous poussez également un tableau d'objets comme ça..push(videoItem);simplement.push(videoItem);.La réponse ci-dessous d'Alex Gray fonctionne :)
n'oubliez pas d'utiliser
const,letouvarlors de la déclaration de variables