You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Chrome扩展Background.ts脚本因Promise调用无法安装?

Chrome扩展Background脚本调用storage初始化函数后崩溃问题

问题详情

我在安装/加载/重载Chrome扩展时,尝试用Promise初始化chrome.storage.local,但调用ModelDataColdSet后Background脚本直接无法运行。使用Node 16.14.2版本,删除ModelDataColdSet(ModelDataColdDefault)这行代码后,脚本就能正常运行并打印[Background]。参考的教程都是类似实现方式,实在搞不懂哪里出问题了。

相关代码

ModelData.ts

export interface ModelData {
  cold?: Object
}

export type ModelDataKeys = keyof ModelData

export const ModelDataColdDefault = {}

export function ModelDataColdSet(cold: Object): Promise<void> {
  const values: ModelData = {
    cold,
  }
  return new Promise((resolve) => {
    chrome.storage.local.set(values, () => {
      resolve()
    })
  })
}

export function ModelDataColdGet(): Promise<Object> {
  const keys: ModelDataKeys[] = ["cold"]
  return new Promise((resolve) => {
    chrome.storage.local.get(keys, (res: ModelData) => {
      resolve(res.cold ?? {})
    })
  })
}

Background.ts

import { ModelDataColdDefault     , ModelDataColdSet }
  from './ModelData';
console.log('[Background]');

chrome.runtime.onInstalled.addListener(() => {
  console.log('Initializing extension');
  ModelDataColdSet(ModelDataColdDefault);
  
  chrome.alarms.create("FeedUpdate", {
    periodInMinutes: 1/60,
  });

  chrome.contextMenus.create({
    "id": "FeedAddSelectionContextMenu",
    "title": "Add selection to broadcast.",
    "contexts": ["selection"]
  });

  chrome.contextMenus.create({
    "id": "FeedAddPageContextMenu",
    "title": "Add current page to your mom."
  });
});

chrome.alarms.onAlarm.addListener((alarm) => {
  console.log('[onAlarm.FeedUpdate]');
  if (alarm.name === "FeedUpdate") {
    console.log('[onAlarm.FeedUpdate]');
  }
});

问题排查与解决方法

1. 检查扩展权限

Chrome扩展使用chrome.storage.local必须在manifest.json中声明storage权限,否则API调用会直接报错导致脚本终止。同时你还用到了alarms和contextMenus,也要一并声明:

{
  "manifest_version": 3,
  "permissions": ["storage", "alarms", "contextMenus"],
  // 其他manifest配置项
}

2. 完善Promise的错误处理

你的ModelDataColdSet只处理了成功回调,没有处理Chrome API调用失败的情况。当API调用出错时(比如权限不足),会产生未捕获的错误,直接终止脚本。修改函数加上错误捕获:

export function ModelDataColdSet(cold: Object): Promise<void> {
  const values: ModelData = {
    cold,
  };
  return new Promise((resolve, reject) => {
    chrome.storage.local.set(values, () => {
      // 检查Chrome API是否返回错误
      if (chrome.runtime.lastError) {
        reject(chrome.runtime.lastError);
      } else {
        resolve();
      }
    });
  });
}

然后在调用时也要捕获错误,避免脚本崩溃:

chrome.runtime.onInstalled.addListener(async () => {
  console.log('Initializing extension');
  try {
    await ModelDataColdSet(ModelDataColdDefault);
    console.log('Storage initialized successfully');
  } catch (error) {
    console.error('Failed to initialize storage:', error);
  }
  
  // 后续的alarms和contextMenus创建代码保持不变
});

3. (可选)优化TypeScript类型

Object类型过于宽泛,建议换成更具体的类型(比如Record<string, unknown>),提升代码健壮性,但这不是导致脚本崩溃的直接原因:

export interface ModelData {
  cold?: Record<string, unknown>
}

export const ModelDataColdDefault: Record<string, unknown> = {}

export function ModelDataColdSet(cold: Record<string, unknown>): Promise<void> {
  // ... 函数内容不变
}

export function ModelDataColdGet(): Promise<Record<string, unknown>> {
  // ... 函数内容不变
}

内容的提问来源于stack exchange,提问作者Cale McCollough

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 01:40:21