簡體   English   中英

.then() 異步中的 while 循環

[英]While loop inside a .then() async

我最近遇到了一個有趣的問題,我一生都無法解決。 我正在調用一個將記錄分解成頁面的 API 調用,頁面的信息駐留在響應標頭中。 從那以后,我希望能夠再次調用以檢索數據和下一個標頭,直到沒有更多響應標頭為止。

let parents = {};

const options = {
  credentials: "same-origin",
  headers: {
    accept: "application/json"
  },
  timeout: 5000
};
fetch(
  `/api/v1/courses/200003/enrollments?enrollment_type=ObserverEnrollment&per_page=100`,
  options
).then(response =>
  response
    .json()
    .then(data => ({
      data: data,
      ok: response.ok,
      headers: response.headers
    }))
    .then(res => {
      parents = res;

      nextURL(res.headers.get("Link"));

      let optionsNext = {
        credentials: "same-origin",
        headers: {
          accept: "application/json"
        },
        timeout: 5000
      };
      fetch(nextURL(res.headers.get("Link")), optionsNext).then(response =>
        response
          .json()
          .then(data => ({
            data: data,
            ok: response.ok,
            headers: response.headers
          }))
          .then(res => {
            if (res.ok) {
              parents.data.push(res.data);
              console.info(parents);
            }
          })
      );
    })
);

function nextURL(linkTxt) {
        let url = null;
        if (linkTxt) {
          let links = linkTxt.split(",");
          let nextRegEx = new RegExp('^<(.*)>; rel="next"$');

          for (let i = 0; i < links.length; i++) {
            let matches = nextRegEx.exec(links[i]);
            if (matches) {
              url = matches[1];
            }
          }
        }
        return url;
      }

我需要放入某種循環的部分是基於 nextURL 函數返回的輔助提取: if !nextURL(res.headers.get("Link"))我需要break循環。

let optionsNext = {
        credentials: "same-origin",
        headers: {
          accept: "application/json"
        },
        timeout: 5000
      };
      fetch(nextURL(res.headers.get("Link")), optionsNext).then(response =>
        response
          .json()
          .then(data => ({
            data: data,
            ok: response.ok,
            headers: response.headers
          }))
          .then(res => {
            if (res.ok) {
              parents.data.push(res.data);
              console.info(parents);
            }
          })
      );

提前感謝您甚至看着我可憐的問題

嘗試使用遞歸; 像這樣:

const getFetcher = () => ({
    aggregate: [],
    run: function (url, options) {
        return new Promise((resolve, reject) => {

            fetch(url, options)
                .then(response => {
                    const json = response.json();
                    const { headers, data } = response;
                    const nextLink = res.headers.get("Link");
                    this.aggregate.push(data);
                    if (nextLink) {
                        this.run(nextLink, options).then(resolve);
                    }
                    else {
                        resolve(this.aggregate);
                    }
                })

        })
    }
})
const options = {
    credentials: "same-origin",
    headers: {
        accept: "application/json"
    },
    timeout: 5000
};
const fetcher = getFetcher();
fetcher.run(`/api/v1/courses/200003/enrollments?enrollment_type=ObserverEnrollment&per_page=100`, options)
    .then(allPagesData => {
        /* at this point you have all the pages data */
    })

使用異步遞歸函數。
我不確定您的 api 返回什么,但這應該有效:
首先,您可以在找到元素時返回該元素,如果元素過多,它可以為您節省幾次迭代。

function nextURL(linkTxt) {
    if (linkTxt) {
      let links = linkTxt.split(",");
      let nextRegEx = new RegExp('^<(.*)>; rel="next"$');

      for (let i = 0; i < links.length; i++) {
        let matches = nextRegEx.exec(links[i]);
        if (matches && matches[1]) {
            //return right away
            return matches[1];
        }
      }
    }
    return null;
}

接下來定義您的主要調用:

const OPTIONS = {
  credentials: "same-origin",
  headers: {
    accept: "application/json"
  },
  timeout: 5000
};
let parents = {};
async function main(){
    const RESPONSE = await fetch(`/api/v1/courses/200003/enrollments?enrollment_type=ObserverEnrollment&per_page=100`,OPTIONS);
    let data = await RESPONSE.json();
    let res = {
        data: data,
        ok: RESPONSE.ok,
        headers: RESPONSE.headers
    }

    loop(res);
    //or: 
    //await loop(res);
    //if you want to wait for it.
}

然后你的循環

const OPTIONS_NEXT = {
    credentials: "same-origin",
    headers: {
      accept: "application/json"
    },
    timeout: 5000
};
async function loop(parents){
    //if nextURL returns null...
    if(nextURL(parents.headers.get("Link")),OPTIONS_NEXT === null) 
        //...end the loop
        return;
    //otherwise keep going.

    const RESPONSE = await fetch(nextURL(parents.headers.get("Link")),OPTIONS_NEXT);
    let data = await RESPONSE.json();
    let res = {
        data: data,
        ok: RESPONSE.ok,
        headers: RESPONSE.headers
    }
    if (res.ok) {
        parents.data.push(res.data);
        console.info(parents);
    }
    loop(res);
    //or: 
    //await loop(res);
    //if you want to wait for it.
    //You need to call it from within an async function.
}

現在你需要做的就是調用 main 函數:

main();
//or: 
//await main();
//if you want to wait for it.
//You need to call it from within an async function.

暫無
暫無

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

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