【问题标题】:make my program wait for an xmlhttprequest to finish让我的程序等待 xmlhttprequest 完成
【发布时间】:2020-06-24 12:51:25
【问题描述】:

我自己可能已经把这个问题复杂化了。我的页面中有 2 个 XMLHTTPRequest,第一个请求从 API 获取一些数据,然后我想用这些数据填充我的元素,现在问题是其中一个我的元素的字段需要向不同的端点发送第二个请求,以使用从第一个请求收到的值之一获取其数据,但它始终填充有 undefined

我知道这是由于请求的异步性质,站点将继续加载并且不会等待请求完成,所以我尝试使第二个请求同步,但同样的事情发生了(只是现在站点冻结了一秒钟),我也尝试使用异步等待,但我的文本编辑器说“等待对这个表达式的类型没有影响”,我完全卡住了..

我相信这是由于我对异步 javascript 缺乏经验和理解(这是我第一个使用它的应用程序).​​.

这是我的代码:

let ourGrid=document.getElementById("res");
let searchValue;
function search(){
    searchValue=document.getElementById("search").value;
    getFoods(`https://api.spoonacular.com/recipes/findByIngredients?ingredients=${searchValue}&number=2&apiKey=${apikey}`);
}

function getFoods(url){
    let xhr=new XMLHttpRequest();
    xhr.responseType='json';
    xhr.onreadystatechange=()=>{
        if(xhr.readyState==XMLHttpRequest.DONE){
            setFoods(xhr.response);
        }else{
            return "error";
        }
    }
    xhr.open('GET',url);
    xhr.send();
}

function setFoods(json){
    if(json.length==0){
        alert(`no results found for ${searchValue}`);
    }else{
    ourGrid.innerHTML=json.map(foodLogic).join("");
    }
    
}

function foodLogic(foodItem){
     return `<div class="imageItem"><img src="${foodItem.image}"></div>
     <div class="infoItem"><h2>${foodItem.title}</h2>
     <p class="summary">${requestSummary(foodItem.id)}</p>
     <p class="more"><a href="./moreInfo.html" target="_blank">More</a></p></div>
     ` 
}

function requestSummary(id){
let url2=`https://api.spoonacular.com/recipes/${id}/summary?apiKey=${apikey}`;
let xhr2=new XMLHttpRequest();
xhr2.onreadystatechange=()=>{
  if(xhr2.readyState==XMLHttpRequest.DONE){
    return returnSummary(JSON.stringify(xhr2.response));
    }
  }    
xhr2.open('GET',url2,false);
xhr2.send();
}

function returnSummary(json){
    return json.summary;
};

【问题讨论】:

  • 你尝试过承诺吗?还是回调?
  • 我想尝试使用一个 Promise,但我不明白如何使它工作,该 Promise 需要一个带有解析和拒绝参数的执行器函数..我不知道在哪里/如何在里面写我自己的功能

标签: javascript ajax xmlhttprequest


【解决方案1】:

您还可以使用承诺或回调。在第一个函数完成后调用第二个函数,并将数据传递给一个改变一切的函数。

在此处获取摘要并传递给下一个函数。

function getFoods(url){
    let xhr=new XMLHttpRequest();
    xhr.responseType='json';
    xhr.onreadystatechange=()=>{
        if(xhr.readyState==XMLHttpRequest.DONE){
            let summary = requestSummary(xhr.response.id);
            setFoods(xhr.response, summary); //pass summary
        }else{
            return "error";
        }
    }
    xhr.open('GET',url);
    xhr.send();
}

现在您可以访问setfoods 中的摘要,随意使用它

function setFoods(json,summary){
    if(json.length==0){
        alert(`no results found for ${searchValue}`);
    }else{
    ourGrid.innerHTML=json.map(foodLogic).join("");
    // Here you have access to summary, use it however you like
    } 
}

【讨论】:

  • 此代码中的摘要请求返回 404 错误
  • 我不知道为什么,但响应 id 返回未定义,这就是为什么我得到 404 ..它之前工作正常
  • 我现在明白了,请求返回一个包含多个对象的 json 数组,我必须遍历每个对象以获取其 id,然后发送第二个请求,这意味着我不能使用这样的要求
【解决方案2】:

我解决了,我决定存储所有的 id,然后在网站和第一个请求的初始内容加载后,我会使用 fetch 请求一个一个地请求 id(因为 ajax 不起作用,我浏览了它的教程),然后到达 html 中的每个摘要元素并按顺序填写。

代码:

let ourGrid=document.getElementById("res");
let searchValue;
let arrid=[];
function search(){
    searchValue=document.getElementById("search").value;
    getFoods(`https://api.spoonacular.com/recipes/findByIngredients?ingredients=${searchValue}&number=2&apiKey=${key}`);
}

function getFoods(url){
    let xhr=new XMLHttpRequest();
    xhr.responseType='json';
    xhr.onreadystatechange=()=>{
        if(xhr.readyState==XMLHttpRequest.DONE){ 
            setFoods(xhr.response);
        }else{
            return "error";
        }
    }
    xhr.open('GET',url);
    xhr.send();
}

function setFoods(json){
    if(json.length==0){
        alert(`no results found for ${searchValue}`);
    }else{
    ourGrid.innerHTML=json.map(foodLogic).join("");
    doId();
    } 
}


function foodLogic(foodItem){
        arrid.push(foodItem.id);
     return `<div class="imageItem"><img src="${foodItem.image}"></div>
     <div class="infoItem"><h2>${foodItem.title}</h2>
     <p class="summary"></p>
     <p class="more"><a href="./moreInfo.html" target="_blank">More</a></p></div>
     ` 
}

function doId(){
    let duh=ourGrid.getElementsByClassName("infoItem");
    for(let i=0;i<arrid.length;i++){
        fetch(`https://api.spoonacular.com/recipes/${arrid[i]}/summary?apiKey=${key}`)
        .then(res=>{return res.json()})
        .then(data=>{
            console.log(data);
            duh[i].getElementsByClassName("summary")[0].innerHTML=data.summary;
        });
    }
}




【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-13
    • 2015-05-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多