单击 Function returns an Empty Array instead of stored JSON reponse

Click Function returns an Empty Array instead of stored JSON reponse

我只是想将一个 JSON 对象存储到一个全局变量中,这样我就不需要在每次更新搜索参数时都 运行 获取(我们正在建造一个房地产列表界面)。下面是我的代码,我确定我误解了 async/await 语法的一些基本内容,因为在元素单击时触发的函数 (filterListings) 正在检索一个空数组。

let allListings = [];
let filteredListings = [];

async function getListings() {
    if(allListings.length == 0){
       let response = await fetch(URL);

       allListings = await response.json();
    }

    filteredListings = allListings;
}

/*Filtering function on search button click*/
function filterListings(){

    filteredListings.length = 0;
    console.log(allListings.length); //allListings is 0???
    for(let i = 0; i < allListings.length; i++){
        console.log("filtering happening");
    }

    numOfListings = filteredListings.length;
    printListings();

}


/*Iterating through filteredListings to get only necessary listings to print on the page*/
function printListings(){
    
    let listingsWrapper = document.getElementById("listings_wrapper");
    let currentPageLimit = ((currentPage !== totalPages) ? listingPageLimit*currentPage : filteredListings.length);
    
    document.getElementById("number_of_listings").innerHTML = numOfListings;
    console.log("These are listings " + listingOffset + " - " + currentPageLimit)
    
    for (let i = listingOffset; i < currentPageLimit; i++) {
      
      listingsWrapper.innerHTML += `<a class='listing_container' href='/listings?address=${styleLink(filteredListings[i].StreetNumber, filteredListings[i].StreetName, filteredListings[i].StreetSuffix, filteredListings[i].City, filteredListings[i].PostalCode, filteredListings[i].MLSNumber)}' style='background-image:url("https://bm-re-listings.s3.us-west-2.amazonaws.com/test_folder/pic-${filteredListings[i].Matrix_Unique_ID}-0.jpg")'>
        <div class='listing_details'>
            <div class='listing_details_main'>
                <h2 class='listing_title'>${styleTitle(filteredListings[i].StreetNumber, filteredListings[i].StreetName, titleCase(filteredListings[i].StreetSuffix), filteredListings[i].City)}</h2>
                <p class='listing_subtitle'>${filteredListings[i].City}, ${filteredListings[i].PostalCode}</p>
                <p class='listing_stats'>${styleRoomNum(filteredListings[i].BedsTotal)}${styleRoomNum(filteredListings[i].BathsTotal)}${filteredListings[i].SqFtTotal} sqft</p>
            </div>
            <div class='listing_details_aside'>
                <h3 class='listing_price'>${stylePrice(filteredListings[i].ListPrice)}</h3>
                <div class='listing_cta'><span>Details</span></div>
            </div>
        </div>
      </a>`
    }
    
    /*Hide load more button if no more listings*/
    if(currentPage == totalPages){
       document.getElementById("load_more").style.display = "none";
    } else {
    document.getElementById("load_more").style.display = "block";   
    }
}


/*Attaching event listner to the search button*/
document.getElementById("search_button").addEventListener("click", function(){
    currentPage = 1;
    listingOffset = (currentPage -1) * listingPageLimit
    
    filterParams.lowPrice = (document.getElementById("price_min").value <= document.getElementById("price_min").getAttribute("min") ? 0 : document.getElementById("price_min").value);
    filterParams.highPrice = (document.getElementById("price_max").value >= document.getElementById("price_max").getAttribute("max") ? 1000000000 : document.getElementById("price_max").value);
    filterParams.lowSqft = (document.getElementById("sqft_min").value <= document.getElementById("sqft_min").getAttribute("min") ? 0 : document.getElementById("sqft_min").value);
    filterParams.highSqft = (document.getElementById("sqft_max").value >= document.getElementById("sqft_max").getAttribute("max") ? 100000 : document.getElementById("sqft_max").value);
    filterParams.address = document.getElementById("address_search").value;
    
    filterListings();
});



/*Final Function Firing Order*/
async function refreshListing(){
    await getListings();
    await printListings();
}
refreshListing();

我发现的问题是,当单击 ID 为“search_button”的元素并触发 filterListings 函数时,它将 return allListings 作为一个空数组,因此 for 循环甚至不会开火。

非常感谢任何帮助!

问题出在filteredListingallListings的引用相同。它们具有相同的基础价值

filteredListings = allListings;

可以在这个简单的例子中观察到这种行为

let allListings;
let filteredListings;
allListings = ['a', 'b', 'c'];
filteredListings = allListings;
console.log(allListings); // ['a', 'b', 'c']
filteredListings.length = 0;
console.log(allListings); // [] 

这个问题在网络上的很多地方都有概述,比如这里Does JavaScript pass by reference?


要修复,只需复制底层对象而不是使用相同的对象即可。对于我们的简单示例:

let allListings;
let filteredListings;
allListings = ['a', 'b', 'c'];
filteredListings = [...allListings]; // copy the array
console.log(allListings); // ['a', 'b', 'c']
filteredListings.length = 0;
console.log(allListings); // ['a', 'b', 'c'] 

对于您的代码,您的函数应为:

async function getListings() {
    if(allListings.length == 0){
       let response = await fetch(URL);

       allListings = await response.json();
    }

    filteredListings = [...allListings]; // clone all listings into filtered
}