前后台发文章的时候添加图片报错Cannot read properties of undefined (reading 'then')
ChatGPT 说:
你这段脚本整体没问题,TinyMCE 初始化和图片上传逻辑都写得对,但出现
Cannot read properties of undefined (reading 'then')
这种错误,说明某个地方调用了一个返回 Promise 的对象(或预期返回 Promise 的函数),但实际返回的是undefined。结合你这段代码,问题 很可能出在images_upload_handler的返回值。
? 问题原因分析
TinyMCE 6 的 images_upload_handler 必须返回一个 Promise,否则 TinyMCE 内部在处理图片上传时会试图调用 .then(),而你的函数当前并没有返回 Promise。
TinyMCE 官方文档说明(官方示例):
The custom
images_upload_handlerfunction must return a Promise, resolving with the image URL or rejecting with an error message.
你当前代码的写法是这样:
images_upload_handler: function (blobInfo, success, failure) {
const xhr = new XMLHttpRequest();
...
xhr.onload = function() { ... }
xhr.open('POST', 'upload.php?act=upload');
xhr.send(formData);
}
这段函数没有 return,因此返回值是 undefined,TinyMCE 在内部执行 images_upload_handler(...).then() 时就会报错。
✅ 正确写法
你需要改成 返回 Promise 的形式,例如:
images_upload_handler: function (blobInfo) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
const formData = new FormData();
xhr.open('POST', 'upload.php?act=upload');
xhr.onload = function () {
if (xhr.status < 200 || xhr.status >= 300) {
reject('HTTP Error: ' + xhr.status);
return;
}
try {
const json = JSON.parse(xhr.responseText);
if (json && json.location) {
resolve(json.location);
} else {
reject('Invalid response: ' + xhr.responseText);
}
} catch (e) {
reject('Invalid JSON response: ' + e.message);
}
};
formData.append('file', blobInfo.blob(), blobInfo.filename());
xhr.send(formData);
});
},
? 补充建议
-
不要同时使用
success/failure回调(那是 TinyMCE 5 旧版写法)。-
TinyMCE 6 只需要返回 Promise。
-
-
服务器端返回格式必须是 JSON
{ "location": "https://example.com/uploads/xxx.jpg" }否则 TinyMCE 无法识别上传结果。
-
可在浏览器控制台确认返回值:
console.log(xhr.responseText);
✅ 总结
-
❌ 当前错误:
images_upload_handler没有返回 Promise。 -
✅ 修复方案:改为返回
new Promise((resolve, reject) => { ... })并在内部调用resolve(json.location)。
这样就不会再出现 Cannot read properties of undefined (reading 'then') 这个错误了。
您说:
帮我把这段代码修复后完整的贴出来
ChatGPT 说:
当然可以 ?
下面是你提供的 完整修正版代码(基于 TinyMCE 6,支持中文、图片上传、Promise 结构正确、并保持你的原有配置和样式不变)?
<script type="text/javascript">
// TinyMCE 6 初始化 - 系统后台版本
document.addEventListener('DOMContentLoaded', function() {
function waitForTinyMCE() {
if (typeof tinymce === 'undefined') {
setTimeout(waitForTinyMCE, 100);
return;
}
tinymce.init({
selector: '#art_content',
language: 'zh_CN',
height: 400,
menubar: false,
branding: false,
plugins: [
'advlist', 'autolink', 'lists', 'link', 'image', 'charmap', 'preview',
'searchreplace', 'visualblocks', 'code', 'fullscreen',
'insertdatetime', 'table', 'wordcount'
],
toolbar: 'undo redo | formatselect | bold italic underline strikethrough | ' +
'alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | ' +
'link image table | code preview fullscreen | removeformat',
content_style: `
body {
font-family: "微软雅黑", Arial, sans-serif;
font-size: 14px;
line-height: 1.6;
color: #333;
margin: 10px;
}
img { max-width: 100%; height: auto; }
p { margin: 0 0 10px 0; }
h1, h2, h3, h4, h5, h6 { margin: 20px 0 10px 0; font-weight: bold; }
`,
// 图片上传配置
images_upload_url: 'upload.php?act=upload',
images_upload_handler: function (blobInfo) {
// ✅ TinyMCE 6 要求必须返回 Promise
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
const formData = new FormData();
xhr.open('POST', 'upload.php?act=upload');
xhr.onload = function() {
if (xhr.status < 200 || xhr.status >= 300) {
reject('HTTP Error: ' + xhr.status);
return;
}
try {
const json = JSON.parse(xhr.responseText);
if (json && json.location) {
resolve(json.location);
} else {
reject('Invalid response: ' + xhr.responseText);
}
} catch (e) {
reject('Invalid JSON response: ' + e.message);
}
};
xhr.onerror = function() {
reject('Image upload failed due to a network error.');
};
formData.append('file', blobInfo.blob(), blobInfo.filename());
xhr.send(formData);
});
},
setup: function(editor) {
editor.on('init', function() {
console.log('✅ TinyMCE 系统编辑器初始化完成');
});
}
});
}
waitForTinyMCE();
});
script>
✅ 改进说明
-
修复错误:旧代码没有返回 Promise,TinyMCE 内部在
.then()时出错。 -
现代写法:去掉
success/failure(那是 TinyMCE 5 的写法)。 -
新增错误处理:
xhr.onerror捕获网络错误,防止无响应时卡死。 -
保持你的样式和功能完全一致(中文界面、编辑器样式、上传逻辑)。


AI工具导航站 - 发现优质实用AI工具网站
洛谷
LearnKu 终身编程者的知识社区
搜狗搜索
屏蔽iphone系统自动升级方法
Krill AI