首页 > 解决方案 > .then() 异步中的 While 循环

问题描述

我最近遇到了一个有趣的问题,我一生都无法解决。我正在调用将记录分解为页面的 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);
            }
          })
      );

提前感谢您甚至看我可怜的问题

标签: javascriptecmascript-6

解决方案


尝试使用递归;像这样的东西:

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

推荐阅读