【问题标题】:Get multiple async urls data, then make action on result (tampermonkey script)获取多个异步 url 数据,然后对结果进行操作(tampermonkey 脚本)
【发布时间】:2021-05-29 18:59:48
【问题描述】:

我对 JS 有点陌生,所以请耐心等待。我正在尝试为网站创建 Tampermonkey (greasyfork) 脚本。

步骤应该是:

  • 检查用户是否登录
  • 如果是,请转到他的“电影分级”页面并加载所有(例如 40 个)页面,获取其 HTML,提取电影分级并将其存储在 LocalStorage 中
  • 完成后,继续执行另一个代码(将列添加到表等...)

现在它可以工作,但它是同步的。因此,当数据不在 LocalStorage 中时,它会非常缓慢地加载每个页面(1page +- 1 秒,典型的是 50-100 页)并且用户等待并且不知道是否发生了任何事情。我的“弹出”功能不适用于“async:false”,但适用于“async:true”。

但是当我使用异步时,它不会等待,并且代码的行为不像我希望的那样。

如果你告诉我“只做一个 Promise,只做一个回调”,我不知道该怎么做。我用谷歌搜索了一天,没有找到任何有用的东西。

我通过工作代码示例/修改来学习。

我现在的代码(简化)

(() => {
    class Csfd {

        constructor(csfdPage) {
            this.csfdPage = csfdPage;
            this.stars = {};  // dict which is then saved as json to LocalStorage
            this.userUrl = undefined;
        }

        getCurrentUser() { ... }
        addRatingsColumn() { ... }

        REFRESH_RATINGS() {
            // Load user ratings...
            $.ajax({
                type: "GET",
                url: this.userRatingsUrl,  // page when pagination of all ratings starts
                async: false
            }).done((data) => {
                this.processRatingsPage(data);
            });

        }

        processRatingsPage(dataHTML) {
            var $stars = this.stars;
            $(dataHTML).find("tbody tr").each(function () {
                let starsRatings .... // simplified line, get the data of each rating row
                $stars[filmURL] = starsRating;
            });

            // Check if there is next page
            let nextPaginationURL = $(dataHTML).find("a.page-next").attr("href");
            if (nextPaginationURL) {
                // Next page exists, fetch it and repeat, add new ratings to `this.stars`
                this.loadPage(nextPaginationURL);
            } else {
                // No next page, finish...
                this.finishRefresh();
            }
        }
        
        loadPage(url) {
            let foundMatch = url.match(new RegExp("page=(.*)$"));
            let currentNum = 1;
            if (foundMatch.length == 2) {
                currentNum = foundMatch[1];
            }
            
            console.log(`${SCRIPTNAME} - Loading... ${currentNum}/${this.endPageNum}`);

            $.ajax({
                type: "GET",
                url: url,
                async: false
            }).done((data) => {
                this.processRatingsPage(data);
            });
        }

        finishRefresh() {
            this.exportRatings();  // export JSON stringify to LocalStorage
        }
    }
    
    // SCRIPT START
    csfd.userUrl = csfd.getCurrentUser();

    // If logged in, do some stuff
    if (csfd.userUrl !== undefined) {
        
        // If movie ratings not loaded in LocalStorage...
        csfd.REFRESH_RATINGS();
   }
   
   // --> THIS IS CALLED BEFORE REFRESH_RATINGS ENDS IF I DO async: true
   if (Object.keys(this.stars).length != 0) {
       // Continue after movie ratings are loaded
       csfd.addRatingsColumn();
   }

}

【问题讨论】:

    标签: javascript asynchronous synchronous


    【解决方案1】:

    您可以将您的 ajax 调用包装在 Promise 中,该调用在调用返回时被解析。像这样的:

    (async () => {
           ...
    
            async REFRESH_RATINGS() {
                // Load user ratings...
                return new Promise((resolve, reject) => { 
                   $.ajax({
                      type: "GET",
                      url: this.userRatingsUrl,  // page when pagination of all ratings starts
                      async: true
                   }).done((data) => {
                      this.processRatingsPage(data);
                      resolve();
                   })
                });
            }
    
           ...
    
           if (csfd.userUrl !== undefined) {
              // If movie ratings not loaded in LocalStorage...
              await csfd.REFRESH_RATINGS();
           }
           ...
    

    【讨论】:

    • 我尝试实现它并测试了一些东西,但无济于事。当这些页面正在加载时,浏览器被冻结,它一个接一个地执行它 - 它的行为就像非异步代码一样。这是我最新的提交。 github.com/SonGokussj4/greasyfork-scripts/blob/async-test/…
    • 所以不再冻结了,我做了一个异步函数(loadPage),这很有帮助。但它不会等...我已经制作了一个调用它的按钮,我不会再刷新 main 函数运行的数据了。不知道怎么做,很奇怪。所以现在它仍然可以工作,几乎就像非异步一样。
    猜你喜欢
    • 1970-01-01
    • 2014-12-20
    • 2021-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-04
    • 2017-08-19
    相关资源
    最近更新 更多