【问题标题】:Undefined return in a 'then' chain'then' 链中的未定义返回
【发布时间】:2021-07-10 09:00:47
【问题描述】:

我正在使用节点和角度构建一个应用程序,当我请求这个特定的端点时,我得到一个空数组“[]”的返回。我将 return 语句放在最后的 'then' 块中,但这会在前一个 for 循环之前执行。

如何使这个同步,以便 realTemps 数组在 for 循环中填充,然后在下一个 then 语句中返回?

router.get("", (req, res, next) => {
var templates = [];
var realTemps = [];
const token = req.headers.authorization.split(" ");
const decoded = jwt.verify(token[1], 'secretkey');
decodedFactoryId = decoded.factoryId

Template.findAllByFactoryId(decodedFactoryId)
    .then((results) => {
        for (var i = 0; i < results.length; i++) {
            // THIS IS AN AVOIDABLE LOOP, quadratic time must be prevented by correctly formatting the data (TODO)
            for (var j = 0; j < results.length; j++) {
                if (results[i][j].id) {
                    templates.push(results[i][j].id)
                }
            }
        }
    }).then(() => {
        console.log("templates: " + templates)
        for (var i = 0; i < templates.length; i++) {
            console.log(templates[i])
            Template.findByTemplateId(templates[i]).then(result => {
                console.log("here is the result: " + JSON.stringify(result[0]))
                realTemps.push(result);
            })

        }
    })
    .then(() => {
        return realTemps;
    })
 })

【问题讨论】:

  • Template.findByTemplateId(templates[i]).then() 仍然会晚于外部 then() 链完成。我建议用awaits 重新编写它,让自己更简单。
  • 如果它在请求函数中,如何将其重写为等待?
  • 如果您愿意,可以通过使其异步或将该逻辑提取到异步函数中然后调用。

标签: javascript node.js mean-stack


【解决方案1】:

只需制作第二个和第三个.then如下

.then(() => Promise.all(templates.map(template => Template.findByTemplateId(template))))
.then((realTemps) => {
    return realTemps;
})

【讨论】:

  • 这里最后一个then()是多余的。
  • 是的,但这就是您要使用 realTemps 的地方 - 问题中的代码远未完成
【解决方案2】:

您应该使用Promise.all 来等待承诺列表。

Template.findAllByFactoryId(decodedFactoryId)
    .then((results) => {
        for (var i = 0; i < results.length; i++) {
            // THIS IS AN AVOIDABLE LOOP, quadratic time must be prevented by correctly formatting the data (TODO)
            for (var j = 0; j < results.length; j++) {
                if (results[i][j].id) {
                    templates.push(results[i][j].id)
                }
            }
        }
    }).then(() => {
      // Promise.all
      return Promise.all(templates.map(template => Template.findByTemplateId(template).then(result => {
        console.log("here is the result: " + JSON.stringify(result[0]))
        realTemps.push(result);
      })))
    })
    .then(() => {
        return realTemps;
    })
 })

为了更好的编码体验,推荐使用async/await,比.then语句更清晰。

【讨论】:

    【解决方案3】:

    你应该在第二个回调中使用Promise.all()

    router.get("", (req, res, next) => {
    var templates = [];
    var realTemps = [];
    const token = req.headers.authorization.split(" ");
    const decoded = jwt.verify(token[1], 'secretkey');
    decodedFactoryId = decoded.factoryId
    
    Template.findAllByFactoryId(decodedFactoryId)
        .then((results) => {
            for (var i = 0; i < results.length; i++) {
                // THIS IS AN AVOIDABLE LOOP, quadratic time must be prevented by correctly formatting the data (TODO)
                for (var j = 0; j < results.length; j++) {
                    if (results[i][j].id) {
                        templates.push(results[i][j].id)
                    }
                }
            }
        }).then(() => Promise.all(templates.map(template => Template.findByTemplateId(template))))
    
        .then((tmpls) => {
            realTemps =  tmpls;
        })
     })
    

    或者使用 async/await 语法:

    router.get("", async (req, res, next) => {
      var templates = [];
      var realTemps = [];
      const token = req.headers.authorization.split(" ");
      const decoded = jwt.verify(token[1], 'secretkey');
      decodedFactoryId = decoded.factoryId
    
      const results = await Template.findAllByFactoryId(decodedFactoryId);
    
      for (var i = 0; i < results.length; i++) {
        // THIS IS AN AVOIDABLE LOOP, quadratic time must be prevented by correctly formatting the data (TODO)
        for (var j = 0; j < results.length; j++) {
          if (results[i][j].id) {
            templates.push(results[i][j].id)
          }
        }
      }
    
      realTemps = await Promise.all(templates.map(template => Template.findByTemplateId(template)));
    })
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-11
      • 2016-03-21
      • 1970-01-01
      • 2020-07-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多