简体   繁体   English

如何在解决之前等待承诺中的所有代码完成? (但稍微复杂一点)

[英]How to wait for all the code in a promise to finish before resolving it? (but a little more complex)

Sorry for the very confusing question, I have this code that gets information from a website without any node modules or libraries.很抱歉这个非常令人困惑的问题,我有这个代码可以从没有任何节点模块或库的网站上获取信息。 It is a list of users separated into different pages use ?page= at the end of the URL.它是一个将用户分成不同页面的列表,使用?page=在 URL 的末尾。 I have managed to iterate through the pages and split up the raw HTML just right.我设法遍历页面并将原始 HTML 拆分得恰到好处。 However, my promise resolves before all the data is collected.但是,我的承诺会在收集所有数据之前解决。 How can I wait for everything to finish before I resolve the promise?在我解决承诺之前,我怎么能等到一切都完成? I have tried countless solutions, but none seem to work.我尝试了无数解决方案,但似乎都没有奏效。 Please don't ask to use a node package, as my goal is to not use one :) A friend helped with the regex and splitting it up.请不要要求使用节点包,因为我的目标是不使用节点包 :) 一位朋友帮助使用正则表达式并将其拆分。 Here is the code I am using:这是我正在使用的代码:

function getData() {
    return new Promise((resolve, reject) => {
        let final = [] //the array of users returned in the end
        const https = require("https"), url = "https://buildtheearth.net/buildteams/121/members";
        https.get(url + "?page=1", request => { //initial request, gets the number of user pages.
            let rawList = '';

            request.setEncoding("utf8"), 
            request.on("data", data => {rawList += data}), 
            request.on("end", () => {
                if(request = (request = (request = rawList.substring(rawList.indexOf('<div class="pagination">'))).substring(0, request.indexOf("</div>"))).match(/<a(.+)>(.+)<\/a>/g)) {
                    for(let t = parseInt(request[request.length - 1].match(/(\d+)(?!.*\d)/g)), a = 1; a < t + 1; a++) { //iterates through member pages
                        https.get(url + "?page=" + a, request2 => { //https request for each page of members
                            let rawList2 = '';
                            
                            request2.setEncoding('utf8'), 
                            request2.on("data", data => {rawList2 += data}), 
                            request2.on("end", () => {
                                let i = rawList2.match(/<td>(.+)<\/td>/g); //finds table in HTML
                                if (i) 
                                    for (var t = 1; t < i.length; t += 3) //iterates through rows in table
                                        console.log(i[t].replace(/<td>/g, "").replace(/<\/td>/g, "")), /* logs element to the console (for testing) */
                                        final.push(i[t].replace(/<td>/g, "").replace(/<\/td>/g, "")); //pushes element to the array that is resolved in the end
                            })
                        })
                        
                    }
                }
                resolve(final) //resolves promise returning final array, but resolves before elements are added with code above
            })
        })
    })
}

If this helps, here is the website I am trying to get info from.如果这有帮助,是我试图从中获取信息的网站。 I am still a little new to JS so if you could help, I would really appreciate it :)我对 JS 还是有点陌生​​,所以如果您能提供帮助,我将不胜感激:)

I ended up turning each action into an async function with a try and catch block and then chained the functions together with .then() For the base (getting data from a website) I took inspiration from an article on Medium .我最终使用trycatch块将每个操作转换为异步函数,然后使用.then()将这些函数链接在一起。对于基础(从网站获取数据),我从Medium一篇文章获得灵感。 Here is the site I am pulling data from, and here is the function to get data from a website:是我从中提取数据的站点,这是从网站获取数据的功能:

const getData = async (url) => {
    const lib = url.startsWith('https://') ? https : http;
  
    return new Promise((resolve, reject) => {
        const req = lib.get(url, res => {
            if (res.statusCode < 200 || res.statusCode >= 300) {
                return reject(new Error(`Status Code: ${res.statusCode}`));
            }

            const data = [];

            res.on('data', chunk => data.push(chunk));
            res.on('end', () => resolve(Buffer.concat(data).toString()));
        });
  
        req.on('error', reject);
        req.end();
    });
};

and then I got the number of pages (which can be accessed by appending ?page=<page number> to the end of the url) with this this function:然后我用这个函数得到了页数(可以通过将?page=<page number>附加到 url 的末尾来访问):

const pages = async () => {
    try {
        let html = await getData('https://buildtheearth.net/buildteams/121/members',);
        let pages = await (html = (html = html.substring(html.indexOf('<div class="pagination">'))).substring(0, html.indexOf("</div>"))).match(/<a(.+)>(.+)<\/a>/g)
        let pageCount = await parseInt(pages[pages.length - 1].match(/(\d+)(?!.*\d)/g))
        return pageCount
    } catch (error) {
        console.error(error);
    }
}

and then I used the page count to iterate through the pages and add the HTML of each to an array with this function:然后我使用页面计数遍历页面并将每个页面的 HTML 添加到具有此函数的数组中:

const getPages = async pageCount => {
    let returns = []
    try {
        for (page = 1; page <= pageCount; page++) {
            try {
                let pageData = await getData('https://buildtheearth.net/buildteams/121/members?page=' + page)
                returns.push(pageData)
            } catch (error) {
                return error
            }
        }
    } catch (error) {
        return error
    } finally {return returns}
}

and then I iterated through the array of strings of HTML of each page, and extracted the data I needed out of each with this function which would return the list of members I need:然后我遍历每个页面的 HTML 字符串数组,并使用此函数从每个页面中提取我需要的数据,该函数将返回我需要的成员列表:

const iteratePages = async pages => {
    if (!Array.isArray(pages)) return
    try {
        let returns = []
        await pages.forEach(page => {
            let list = page.match(/<td>(.+)<\/td>/g);
            if (list)
                for (var element = 1; element < list.length; element += 3)
                    returns.push(list[element].replace(/<td>/g, "").replace(/<\/td>/g, ""));
        })
        return returns
    } catch (error) {
        return error
    }   
}

And then it was a matter of chaining each together to get the array I needed:然后是将每个链接在一起以获得我需要的数组的问题:

pages().then(pageCount => getPages(pageCount)).then(pages => iteratePages(pages)).then(finalList => {console.log(finalList); console.log(finalList.length)})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 等待Promise.all内部的诺言完成后再解决 - Wait for promises inside Promise.all to finish before resolving it 等待嵌套的JS诺言完成,然后再解决原始诺言 - Wait for nested JS promise to finish before resolving original promise 如何在函数返回之前等待promise完成 - How to wait for promise to finish before function returns 如何在解决承诺之前正确地让 jest axios 模拟等待 - How to properly have jest axios mock wait before resolving promise 在返回 function 的变量之前,如何等待 promise 完成? - How do I wait for a promise to finish before returning the variable of a function? 如何在从我的 promise / function 返回之前等待 forEach 完成 - How to wait for a forEach to finish before returning from my promise / function 如何等待所有 Promise.all() 完成然后继续结果 - How to wait for all Promise.all() to finish and then continue with the results 如何等待Promise.all中的Promise.all中的2个完成并执行其他任务 - How to wait for 2 of Promises in Promise.all to finish and then do another task 如何在解决promise之前确保将所有数据都推送到阵列? - How to make sure that all data are pushed to the array before resolving promise? 如何在返回结果之前等待 javascript 完成所有功能 - how to make wait javascript to finish all functions before return result
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM