为了账号安全,请及时绑定邮箱和手机立即绑定

为什么即使在等待所有承诺解决之后,最终的 console.log 也没有显示整个数据?

为什么即使在等待所有承诺解决之后,最终的 console.log 也没有显示整个数据?

温温酱 2022-10-27 14:33:21
编辑因此,如果我setTimeout在 final 上设置 a console.log,它会很好地记录下来,但我想我的新问题是,即使有then陈述,为什么在一切都解决之后它不会触发?我有一个奇怪的错误,我无法弄清楚为什么它没有打印我期望的整个结构。我没有收到任何错误,我确实尝试输入了一些console.log,但似乎只是让anyOf属性记录下来。它总是显示为空。我的主要问题是hold没有正确记录。它显示anyOf为空。const $ = require('cheerio');const Axios = require('axios').default;let name = 'sqs';let basePath = '/AWS_SQS.html'let hold = {    '$schema': 'http://json-schema.org/draft-07/schema#',    '$id': `cf${name}`,    'description': `CF ${name}`,    'properties': {        'Type': {            'type': 'string',            'enum': [],        },    },    'anyOf': [] // this keeps coming up empty};let typeProperties = (t, p) => {    return {        'if': { 'properties': { 'Type': { 'const': t } } },        'then': {            'properties': {                'Properties': {                    'type': 'object',                    'properties': p,                },            },        },    }}const makeRequest = (bpath) => {    let url = 'https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/' + bpath    return Axios.get(url)        .then((res) => {            return res.data;        })        .catch(console.log);};let getData = makeRequest(basePath).then((data) => {    let match = $('.listitem>p>a', data);    match.map((i, e) => {        let t = $(e);        hold.properties.Type.enum.push(t.text());        makeRequest(t.attr('href')).then((newdata) => {            let holdProperties = {}            let pType = $($('.variablelist', newdata)[0])            $('.term>.code', pType).map((i, elem) => {                let propertyName = $(elem).text()                holdProperties[propertyName] = {}            })            hold.anyOf.push(typeProperties(t.text(), holdProperties))        }).catch(console.log)    });}).catch(console.log)getData.then(() => {    // Why doesnt this log fully once everything is resolved? If i put a setTimeout here, it will work fine    console.log(JSON.stringify(hold));}).catch(console.log)
查看完整描述

1 回答

?
收到一只叮咚

TA贡献1821条经验 获得超5个赞

在与 关联的代码中getData(),您正在执行makeRequest().then()a .map(),但完全忽略了返回的承诺makeRequest()。你不是在等他们。您需要使用Promise.all()来等待所有这些,这样您就可以返回一个与所有其他完成的承诺相关联的承诺。


你可以这样做:


let getData = makeRequest(basePath).then((data) => {

    let match = $('.listitem>p>a', data).get();

    return Promise.all(match.map(item => {

        let t = $(item);

        hold.properties.Type.enum.push(t.text());

        return makeRequest(t.attr('href')).then((newdata) => {

            let holdProperties = {}

            let pType = $($('.variablelist', newdata)[0])

            $('.term>.code', pType).map((i, elem) => {

                let propertyName = $(elem).text()

                holdProperties[propertyName] = {}

            })

            hold.anyOf.push(typeProperties(t.text(), holdProperties))

        }).catch(err => {

            console.log(err);

            throw err;              // propagate error back to caller

        });

    }));

}).catch(console.log)


getData.then(() => {

    // Why doesnt this log fully once everything is resolved? If i put a setTimeout here, it will work fine

    console.log(JSON.stringify(hold));

}).catch(console.log)

这段代码的变化:

  1. .map()addreturn这样你就有了return makeRequest(...),所以你.map()会返回一个 promises 数组。

  2. 有了这些来自.map()use的承诺,return Promise.all(match.map(...))所以你正在等待来自的所有承诺.map(),所以你正在返回那个摘要承诺。

  3. 使用从 jQuery/cheerio 获取真正的数组,.get()以便您可以使用真正的 ES6 迭代操作。

  4. 然后将参数切换.map()为匹配array.map()使用的内容。

请注意,您的hold.anyOf数组的结果将无法保证顺序,因为您的所有并行makeRequest()调用都可以按任何顺序完成。如果您希望它们按顺序排列,您应该从.then()处理程序返回值,然后按顺序累积所有值,然后您可以从数组中使用它们,该数组是它们按照您请求它们的顺序Promise.all()的解析值。Promise.all()


查看完整回答
反对 回复 2022-10-27
  • 1 回答
  • 0 关注
  • 144 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号