【问题标题】:Await asynchronous function before module.exports在 module.exports 之前等待异步函数
【发布时间】:2019-07-13 06:50:54
【问题描述】:

我有一个 NextJS 应用程序,并且正在使用 next-routes 来处理所有路由。

我的路由模块目前如下所示:

const routes = require('next-routes')();
const { getEntries } = require('../data/contentful');

module.exports = async () => {
  const globalSettings = await getEntries({
    content_type: 'globalSettings',
  });

  routes
    .add('caseStudies', `/${globalSettings.fields.caseStudiesSlug}`, 'caseStudies')
    .add('caseStudy', `/${globalSettings.fields.caseStudiesSlug]}/:slug`, 'caseStudy')
    .add('home', `/`, 'index')
    .add('page', `/:slug*`, 'page'));

  return routes;
};

我可以让它在服务器端工作,但要在客户端使用下一个路由,我需要这个模块立即返回路由对象而不是异步函数。例如

const routes = require('next-routes')();
const { getEntries } = require('../data/contentful');

// Do this first, then module.exports
const globalSettings = await getEntries({
  content_type: 'globalSettings',
});

module.exports = routes
  .add('caseStudies', `/${globalSettings.fields.caseStudiesSlug}`, 'caseStudies')
  .add('caseStudy', `/${globalSettings.fields.caseStudiesSlug]}/:slug`, 'caseStudy')
  .add('home', `/`, 'index')
  .add('page', `/:slug*`, 'page'));

这不起作用,因为await 必须在异步函数中。如何在执行路由对象的 module.exports 之前完成异步 API 调用?

【问题讨论】:

  • 我不确定你是否可以,因为require 是同步的,它不能等待 API 调用结束来导入你的模块。顺便说一句,假设您的服务器在十几秒内回答,您希望它做什么?如果它可以等待您的 api 调用结束,它可能会冻结您的服务器,直到它完成。
  • 为什么又需要同步?
  • @KevinB 因为可以在客户端导入下一个路由对象并像这样解构import { Link } from '../routes';
  • 等等...所以你想要同步的唯一原因是你可以解构它? imo有点傻。
  • @KevinB 这就是 next-routes 包的工作方式。它是 NextJS 的一个受欢迎的补充,而不是我可以控制的东西。

标签: javascript node.js express next.js


【解决方案1】:

这是this renowned problem 的一个特例。同步代码可以转换为异步代码,反之则不行。

this similar answer 所示,如果需要,应将promise 使用到应用程序入口点:

module.exports = (async () => {
  const globalSettings = await getEntries({
    content_type: 'globalSettings',
  });

  return routes
  .add('caseStudies', `/${globalSettings.fields.caseStudiesSlug}`, 'caseStudies')
  .add('caseStudy', `/${globalSettings.fields.caseStudiesSlug]}/:slug`, 'caseStudy')
  .add('home', `/`, 'index')
  .add('page', `/:slug*`, 'page'));
})();

这个模块还导出了一个 Promise,所以它需要被链接到一个依赖它的模块中。

a proposal for top-level await 旨在为此配方提供语法糖。

【讨论】:

  • 顶级等待正是我所需要的!
  • 遗憾的是,它甚至还没有被本地批准和实施。像答案所示导出异步 IIFE 并使用 await require('async-module') 导入它们是我们现在所拥有的。可以看到提案其实是这么描述的,github.com/tc39/…
  • 那时我正在努力寻找解决问题的方法。基本上在服务器端,我需要调用 globalSettings API 并构建路由对象。然后在客户端,我希望能够访问该路由对象而无需再次进行 API 调用。
  • 我自己不使用 Next。如果您在客户端从服务器端访问对象时遇到问题,那么这是更具体的问题。基本上这是通过使用<script>window.__MY_DATA__ = 'data from server side'</script> 呈现索引页面来完成的,但可能会有特定于 Next 的解决方案。
猜你喜欢
  • 2020-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-02
  • 2023-03-13
  • 2021-03-06
相关资源
最近更新 更多