函数
🌐 Functions
Page summary:
src/index托管全局注册、引导和销毁函数,以在应用生命周期中运行逻辑。
可用模式
🌐 Available modes
生命周期函数支持三种执行模式,因此你可以将它们与它们管理的依赖对齐。Strapi 会等待每个函数完成,无论它是正常返回、解析一个 async 函数,还是解析一个 Promise,然后才继续启动或关闭过程。
🌐 Lifecycle functions support 3 execution patterns/modes so you can align them with the dependencies they manage. Strapi waits for each function to finish, whether it returns normally, resolves an async function, or resolves a promise, before moving on with startup or shutdown.
Strapi 不使用返回值,因此函数应仅在设置或清理完成后才解析(或返回),并在失败时抛出异常或拒绝。
🌐 Return values aren't used by Strapi, so the functions should resolve (or return) only when their setup or cleanup is complete and throw or reject to signal a failure.
同步
🌐 Synchronous
同步函数运行的逻辑会立即完成,无需等待其他异 步任务。
🌐 Synchronous functions run logic that completes immediately without awaiting other asynchronous tasks.
- JavaScript
- TypeScript
module.exports = {
register({ strapi }) {
strapi.log.info('Registering static configuration');
},
bootstrap({ strapi }) {
strapi.log.info('Bootstrap finished without awaiting tasks');
},
destroy({ strapi }) {
strapi.log.info('Server shutdown started');
}
};
export default {
register({ strapi }) {
strapi.log.info('Registering static configuration');
},
bootstrap({ strapi }) {
strapi.log.info('Bootstrap finished without awaiting tasks');
},
destroy({ strapi }) {
strapi.log.info('Server shutdown started');
}
};
异步
🌐 Asynchronous
异步函数使用 async 关键字来 await 任务,例如 API 调用或数据库查询,然后 Strapi 才继续。
🌐 Asynchronous functions use the async keyword to await tasks such as API calls or database queries before Strapi continues.
- JavaScript
- TypeScript
module.exports = {
async register({ strapi }) {
await new Promise((resolve) => setTimeout(resolve, 200));
strapi.log.info('Async register finished after a short delay');
},
async bootstrap({ strapi }) {
const { results: articles } = await strapi
.documents('api::article.article')
.findMany({
filters: { publishedAt: { $notNull: true } },
fields: ['id'],
});
strapi.log.info(`Indexed ${articles.length} published articles`);
},
async destroy({ strapi }) {
await strapi.documents('api::temporary-cache.temporary-cache').deleteMany({
filters: {},
});
}
};
export default {
async register({ strapi }) {
await new Promise((resolve) => setTimeout(resolve, 200));
strapi.log.info('Async register finished after a short delay');
},
async bootstrap({ strapi }) {
const { results: articles } = await strapi
.documents('api::article.article')
.findMany({
filters: { publishedAt: { $notNull: true } },
fields: ['id'],
});
strapi.log.info(`Indexed ${articles.length} published articles`);
},
async destroy({ strapi }) {
await strapi.documents('api::temporary-cache.temporary-cache').deleteMany({
filters: {},
});
}
};
返回一个承诺
🌐 Returning a promise
返回 Promise 的函数会返回一个 Promise,以便 Strapi 可以等待其解析后再继续执行。
🌐 Promise-returning functions hand back a promise so Strapi can wait for its resolution before continuing.
- JavaScript
- TypeScript
module.exports = {
register({ strapi }) {
return new Promise((resolve) => {
strapi.log.info('Registering with a delayed startup task');
setTimeout(resolve, 200);
});
},
bootstrap({ strapi }) {
return new Promise((resolve, reject) => {
strapi
.documents('api::category.category')
.findMany({ filters: { slug: 'general' }, pageSize: 1 })
.then(({ results }) => {
if (results.length === 0) {
return strapi.documents('api::category.category').create({
data: { name: 'General', slug: 'general' },
});
}
return results[0];
})
.then(() => {
strapi.log.info('Ensured default category exists');
resolve();
})
.catch(reject);
});
},
destroy({ strapi }) {
return new Promise((resolve, reject) => {
strapi
.documents('api::temporary-cache.temporary-cache')
.deleteMany({ filters: {} })
.then(() => {
strapi.log.info('Cleared temporary cache before shutdown');
resolve();
})
.catch(reject);
});
}
};
export default {
register({ strapi }) {
return new Promise((resolve) => {
strapi.log.info('Registering with a delayed startup task');
setTimeout(resolve, 200);
});
},
bootstrap({ strapi }) {
return new Promise((resolve, reject) => {
strapi
.documents('api::category.category')
.findMany({ filters: { slug: 'general' }, pageSize: 1 })
.then(({ results }) => {
if (results.length === 0) {
return strapi.documents('api::category.category').create({
data: { name: 'General', slug: 'general' },
});
}
return results[0];
})
.then(() => {
strapi.log.info('Ensured default category exists');
resolve();
})
.catch(reject);
});
},
destroy({ strapi }) {
return new Promise((resolve, reject) => {
strapi
.documents('api::temporary-cache.temporary-cache')
.deleteMany({ filters: {} })
.then(() => {
strapi.log.info('Cleared temporary cache before shutdown');
resolve();
})
.catch(reject);
});
}
};
生命周期函数
🌐 Lifecycle functions
生命周期函数允许你在 Strapi 启动和关闭的特定阶段放置代码。
🌐 Lifecycle functions let you place code at specific phases of Strapi's startup and shutdown.
register()函数用于服务启动前的配置时设置。bootstrap()函数用于需要 Strapi API 的初始化。destroy()函数用于在应用停止时进行清理。
注册
🌐 Register
register 生命周期函数,位于 ./src/index.js(或在 ./src/index.ts 中),是一个在应用初始化之前运行的异步函数。
🌐 The register lifecycle function, found in ./src/index.js (or in ./src/index.ts), is an asynchronous function that runs before the application is initialized.
register() 是 Strapi 应用启动时发生的第一件事。这发生在任 何设置过程之前,并且在 register() 函数中你无法访问数据库、路由、策略或任何其他后端服务器元素。
register() 函数可以用于:
🌐 The register() function can be used to:
- 扩展插件
- 以编程方式扩展 content-types
- 加载一些 环境变量
- 注册一个自定义字段,该字段仅供当前 Strapi 应用使用,
- 注册一个 自定义提供程序用于 Users & Permissions 插件。
更具体地说,register() 的典型用例包括前置安全任务,例如在应用完成初始化之前加载密钥、轮换 API 密钥或注册认证提供者。
🌐 More specifically, typical use-cases for register() include front-load security tasks such as loading secrets, rotating API keys, or registering authentication providers before the app finishes initializing.
- JavaScript
- TypeScript
module.exports = {
register({ strapi }) {
strapi.customFields.register({
name: 'color',
plugin: 'my-color-picker',
type: 'string',
});
},
};
export default {
register({ strapi }) {
strapi.customFields.register({
name: 'color',
plugin: 'my-color-picker',
type: 'string',
});
},
};
自举
🌐 Bootstrap
bootstrap 生命周期函数,位于 ./src/index.js(或 ./src/index.ts 中),在每次服务器启动时都会被调用。
🌐 The bootstrap lifecycle function, found in ./src/index.js (or in ./src/index.ts), is called at every server start.
bootstrap() 会在后端服务器启动之前但在 Strapi 应用设置之后运行,因此你可以访问 strapi 对象中的任何内容。
bootstrap 函数可以用于:
🌐 The bootstrap function can be used to:
- 如果没有管理员用户,请创建一个
- 用一些必要的数据填充数据库
- 为 基于角色的访问控制 (RBAC) 功能声明自定义条件
更具体地说,bootstrap() 的典型用例是支持编辑工作流程。例如,通过提供初始内容、附加 webhook,或在启动时安排 cron 作业。
🌐 More specifically, a typical use-case for bootstrap() is supporting editorial workflows. For example by seeding starter content, attaching webhooks, or scheduling cron jobs at startup.
你可以在终端中运行 yarn strapi console(或 npm run strapi console)并与 strapi 对象进行交互。
🌐 You can run yarn strapi console (or npm run strapi console) in the terminal and interact with the strapi object.
- JavaScript
- TypeScript
module.exports = {
async bootstrap({ strapi }) {
const { results } = await strapi
.documents('api::category.category')
.findMany({ filters: { slug: 'general' }, pageSize: 1 });
if (results.length === 0) {
await strapi.documents('api::category.category').create({
data: { name: 'General', slug: 'general' },
});
strapi.log.info('Created default category');
}
},
};
export default {
async bootstrap({ strapi }) {
const { results } = await strapi
.documents('api::category.category')
.findMany({ filters: { slug: 'general' }, pageSize: 1 });
if (results.length === 0) {
await strapi.documents('api::category.category').create({
data: { name: 'General', slug: 'general' },
});
strapi.log.info('Created default category');
}
},
};
摧毁
🌐 Destroy
./src/index.js(或./src/index.ts)中的destroy函数是一个异步函数, 会在应用关闭之前运行。
🌐 The destroy function, found in ./src/index.js (or in ./src/index.ts), is an asynchronous function that runs before the application gets shut down.
destroy 函数可用于优雅地:
🌐 The destroy function can be used to gracefully:
更具体地说,destroy() 的一个典型用例是处理操作清理,例如关闭数据库或队列连接以及移除监听器,以便应用能够干净地关闭。
🌐 More specifically, a typical use-case for destroy() is to handle operational clean-up, such as closing database or queue connections and removing listeners so the application can shut down cleanly.
- JavaScript
- TypeScript
let heartbeat;
module.exports = {
async bootstrap({ strapi }) {
heartbeat = setInterval(() => {
strapi.log.debug('Heartbeat interval running');
}, 60_000);
},
async destroy() {
clearInterval(heartbeat);
},
};
let heartbeat: ReturnType<typeof setInterval>;
export default {
async bootstrap({ strapi }) {
heartbeat = setInterval(() => {
strapi.log.debug('Heartbeat interval running');
}, 60_000);
},
async destroy() {
clearInterval(heartbeat);
},
};
使用
🌐 Usage
组合使用
🌐 Combined usage
所有 3 个生命周期函数可以组合使用,以配置应用启动和关闭期间的自定义行为。
🌐 All 3 lifecycle functions can be put together to configure custom behavior during application startup and shutdown.
- 确定逻辑的运行时间。
- 在
register()中添加仅初始化任务(例如,注册自定义字段或提供程序)。 - 在
bootstrap()中添加需要完整 Strapi 访问权限的启动任务(例如,播种或附加网页钩子)。 - 在
destroy()中添加清理逻辑(例如关闭外部连接)。
- 在
- 将代码放入
src/index.js|ts。保持register()精简,因为它在 Strapi 完全设置之前运行。 - 重启 Strapi 以确认每个生命周期按顺序执行。
let cronJobKey: string | undefined;
export default {
register({ strapi }) {
strapi.customFields.register({
name: 'color',
type: 'string',
plugin: 'color-picker',
});
},
async bootstrap({ strapi }) {
cronJobKey = 'log-reminders';
strapi.cron.add({
[cronJobKey]: {
rule: '0 */6 * * *', // every 6 hours
job: async () => {
strapi.log.info('Remember to review new content in the admin panel.');
},
},
});
},
async destroy({ strapi }) {
if (cronJobKey) {
strapi.cron.remove(cronJobKey);
}
},
};
你可能会在 this blog article 中找到关于注册生命周期函数的更多信息。