Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/434.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 异步迭代API结果_Javascript_Async Await - Fatal编程技术网

Javascript 异步迭代API结果

Javascript 异步迭代API结果,javascript,async-await,Javascript,Async Await,我正在调用一个API,该API在页面中返回结果,我试图找到一种“优雅”的方法来检索结果 理想情况下,我想这样消费它们: let results = api.get(); for await (const page of results) { // do stuff with page } class Results { constructor(url, token) { this.url = url; this.token = token;

我正在调用一个API,该API在页面中返回结果,我试图找到一种“优雅”的方法来检索结果

理想情况下,我想这样消费它们:

let results = api.get();

for await (const page of results) {
    // do stuff with page
}
class Results {
    constructor(url, token) {
        this.url = url;
        this.token = token;
    }

    async *page() {
        let url = this.url;

        while (true) {
            const response = await fetch(url, {
                headers: { 'Authorization': 'Bearer ' + this.token }
            });

            const data = await response.json();

            yield data.values;

            if (!data.next) return;
            url = data.next;
       }
    }
}
class Response {
    constructor(url, token) {
        this.url = url;
        this.header = {
            headers: {
                Authorization: `Bearer ${token}`
            }
        };
    }

    async* [Symbol.asyncIterator]() {
        let url = this.url;

        const getPage = url =>
            fetch(url, this.header)
                .then(response => response.json())
                .then(data => ({
                    next: data.next,
                    values: data.values
                }));

        while (url) {
            const page = await getPage(url);

            for (const value of page.values) {
                yield value;
            }

            url = page.next;
        }
    }
}
for await (const item of response) {
    ...
}
我可以使用以下生成器函数激活此函数:

let results = api.get();

for await (const page of results) {
    // do stuff with page
}
class Results {
    constructor(url, token) {
        this.url = url;
        this.token = token;
    }

    async *page() {
        let url = this.url;

        while (true) {
            const response = await fetch(url, {
                headers: { 'Authorization': 'Bearer ' + this.token }
            });

            const data = await response.json();

            yield data.values;

            if (!data.next) return;
            url = data.next;
       }
    }
}
class Response {
    constructor(url, token) {
        this.url = url;
        this.header = {
            headers: {
                Authorization: `Bearer ${token}`
            }
        };
    }

    async* [Symbol.asyncIterator]() {
        let url = this.url;

        const getPage = url =>
            fetch(url, this.header)
                .then(response => response.json())
                .then(data => ({
                    next: data.next,
                    values: data.values
                }));

        while (url) {
            const page = await getPage(url);

            for (const value of page.values) {
                yield value;
            }

            url = page.next;
        }
    }
}
for await (const item of response) {
    ...
}
并称之为:

for await (const page of results.page()) {
    // do stuff with page
}
我曾尝试使用类似这样的[Symbol.iterator]进行此操作,但无法使其正常工作:

[Symbol.iterator]() {
    let that = this;

    return {
        next: async function() {

            if (!that.page) {
                that.page = that.url;
                return {done: true};
            }

            const response = await fetch(that.page, {
                headers: { 'Authorization': 'Bearer ' + that.token }
            });

            const data = await response.json();

            that.page = data.data.next;

            return {
                value: data,
                done: false
            }
        }
    }
} 
这个问题是我需要从当前页面获取到下一页的链接,以确定是否有下一页,但作为承诺,我无法在函数中访问它


如何使迭代器工作,有什么想法吗?

下面的建议是一个工作函数<代码>[Symbol.asyncierator]造成了所有的不同。谢谢:

[Symbol.asyncIterator]() {
    let that = this;

    return {
      page: that.url,
      token: that.token,
      next: async function() {

        if (!this.page) {
            this.page = that.url;
            return {done: true};
        }

        const response = await fetch(this.page, {
            headers: { 'Authorization': 'Bearer ' + this.token }
        });

        const data = await response.json();

        this.page = data.next;

        return {
          value: data,
          done: false
        }
    }
}
现在,它的工作原理非常理想,我只想能够遍历所有结果,而不了解页面,因此这里有一个有效的解决方案,可供参考:

[Symbol.asyncIterator]() {
    let that = this;

    return {
      page: that.url,
      token: that.token,
      values: [],
      next: async function() {

        if (!this.page && this.values.length === 0) {
            this.page = that.url;
            return {done: true};
        }

        if (this.values.length > 0) {
            return {
                value: this.values.pop(),
                done: false
            }
        }

        const response = await fetch(this.page, {
            headers: { 'Authorization': 'Bearer ' + this.token }
        });

        const data = await response.json();
        this.page = data.next;
        this.values = data.values;

        if (this.values.length === 0) {
            return { done: true }
        }

        return {
          value: this.values.pop(),
          done: false
        }
    }
}
使用异步生成器函数可以简化此代码,如下所示:

async *[Symbol.asyncIterator]() {
    let url = this.url;

    const getPage = url =>
       fetch(url, this.header)
           .then(response => response.json())
           .then(data => ({
               next: data.next,
               values: data.values
           }));

    while(url) {
        const page = await getPage(url);

        for (const value of page.values) {
            yield value;
        }

        url = page.next;
    }
}
因此,整个类如下所示:

let results = api.get();

for await (const page of results) {
    // do stuff with page
}
class Results {
    constructor(url, token) {
        this.url = url;
        this.token = token;
    }

    async *page() {
        let url = this.url;

        while (true) {
            const response = await fetch(url, {
                headers: { 'Authorization': 'Bearer ' + this.token }
            });

            const data = await response.json();

            yield data.values;

            if (!data.next) return;
            url = data.next;
       }
    }
}
class Response {
    constructor(url, token) {
        this.url = url;
        this.header = {
            headers: {
                Authorization: `Bearer ${token}`
            }
        };
    }

    async* [Symbol.asyncIterator]() {
        let url = this.url;

        const getPage = url =>
            fetch(url, this.header)
                .then(response => response.json())
                .then(data => ({
                    next: data.next,
                    values: data.values
                }));

        while (url) {
            const page = await getPage(url);

            for (const value of page.values) {
                yield value;
            }

            url = page.next;
        }
    }
}
for await (const item of response) {
    ...
}
它允许您轻松地循环浏览分页API结果,如下所示:

let results = api.get();

for await (const page of results) {
    // do stuff with page
}
class Results {
    constructor(url, token) {
        this.url = url;
        this.token = token;
    }

    async *page() {
        let url = this.url;

        while (true) {
            const response = await fetch(url, {
                headers: { 'Authorization': 'Bearer ' + this.token }
            });

            const data = await response.json();

            yield data.values;

            if (!data.next) return;
            url = data.next;
       }
    }
}
class Response {
    constructor(url, token) {
        this.url = url;
        this.header = {
            headers: {
                Authorization: `Bearer ${token}`
            }
        };
    }

    async* [Symbol.asyncIterator]() {
        let url = this.url;

        const getPage = url =>
            fetch(url, this.header)
                .then(response => response.json())
                .then(data => ({
                    next: data.next,
                    values: data.values
                }));

        while (url) {
            const page = await getPage(url);

            for (const value of page.values) {
                yield value;
            }

            url = page.next;
        }
    }
}
for await (const item of response) {
    ...
}

使用
Symbol.iterator
意味着它必须是一个返回值/完成对的常规同步iterable。您的示例返回了一个值/完成对的承诺,因此我认为您可能正在寻找
Symbol.asyncierator
,它用于异步iterables,比如您的异步iterables。很有趣……但似乎有些过分了。每个页面是由不同的URL表示,还是只是由不同的查询参数表示?您应该将当前的
页面
存储在迭代器对象上,而不是存储在
结果
实例上。我认为您的代码应该可以工作,你所需要做的就是使用
Symbol.asyncIterator
而不是
Symbol.iterator
使wait循环按预期使用它。我认为你应该发布你的更新,而不是编辑你的问题