簡體   English   中英

Javascript - .push() 多個對象從 for 循環到多維數組

[英]Javascript - .push() multiple objects from for loop into multidimensional array

我正在運行一個函數,需要將 16 個對象推送到多維數組的i位置。 我可以使用videoData.push(videoItem)將所有數據推送到var = videoData但我最終需要得到一個多維數組,其中每個嵌套數組包含 16 個對象。

//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);
        });
    }
}

我希望最終...

var videoData = [[vid01, vid02....vid16], [vid01, vid02... vid16]]

For循環是同步工作的,當在for循環內執行異步操作時,當for循環完成承諾時,它就會執行。 因此, i的值將具有每個已解決承諾中最后一次循環迭代的值。

我不認為這里真的需要for循環,創建一個函數可以更簡單,該函數接受一個標簽並返回一個解析為 16 個元素的數組的承諾,它可能如下所示:

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)
  })
}

您想使用與此類似的循環來構建多維數組

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);
  }
}

您當前的代碼存在很多問題。 我將從頭開始,希望你能看到更好的方法來解決這個問題。 首先,axios 有很多底層的特性,每次取 json 時都不用關心。 fetchJson東西開始 -

const fetchJson = (url = "") =>
  axios
    ( { method: "get"
      , url
      , headers: { "Content-Type": "application/json" }
      }
    )
    .then(res => res.data)

現在,當我們編寫fetchVideos ,我們可以依賴fetchJson並直接跳轉到我們需要對解析的響應執行的操作 -

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

fetchVideo不依賴於不同的countriestags數組, fetchVideo采用對象輸入,例如 -

fetchVideos({ country: "GB", tag: "?tags=english" })
  .then(console.log, console.error)

它將輸出一個對象,例如 -

// { country: "GB", videos: [ v1, v2, v3, ... ] }

這可以防止需要使用粗索引將值鏈接在一起。 我們通過依賴另一個函數videoFromApi保持fetchVideos高水平。 此函數會將 API 的視頻響應數據轉換為我們應用程序所需的形狀 -

const videoFromApi =
  ( { slug = ""
    , image = ""
    , title = ""
    , description = ""
    }
  , id = 0
  ) =>
    Object.assign
      ( { keys: { video: `vid${id + 1}` } }
      , { values:
          { url: slug 
          , thumb: image
          , title: title
          , desc: description
          }
        }
      )

現在來把這些都在一起,我們定義的數組requests ,並使用Promise.allfetchVideos為每個請求。 注意,這使我們能夠准確地知道所有 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" }
  ]

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, ... ] }
// ]

要查看功能演示,請展開下面的代碼段並運行它。 axios已與randomVideos一起模擬,以便我們可以模擬 API 請求 -

 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, ... ] } // ]

好吧,你不能做這個"videoData[i].push"因為數組上的位置不存在。 你可以使用這樣的輔助數組來解決這個問題:

videoData = []
videoDataAux = []

然后:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM