首页 > 解决方案 > 获取多个异步 url 数据,然后对结果进行操作(tampermonkey 脚本)

问题描述

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

步骤应该是:

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

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

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

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

我现在的代码(简化)

(() => {
    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();
   }

}

标签: javascriptasynchronoussynchronous

解决方案


您可以将 ajax 调用包装Promise在调用返回时解析的 a 中。像这样的东西:

(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();
       }
       ...

推荐阅读