我目前正在学习Node JS和Javascript。我正在尝试开发一个应用程序来阅读和下载Mangas。
首先,我想建立一个数据库。这是我遇到问题的地方。 当我在我的服务器上运行我的程序有4GB的RAM(以填充我的数据库)我得到致命错误Javascript堆内存不足。
当我在本地计算机上使用8GB内存运行相同程序时,一切都按预期运行。
以下是我用Manga Chapters填充数据库的代码。
function insertChapters(callback){
sql_selectAll("Mangas", function (selectError, selectResult) {
if(!selectError){
selectResult.forEach(function (mangaItem, mangaIndex) {
gin.mangafox.chapters(mangaItem.Title)
.then(chapters =>{
chapters.forEach(function (chapterItem) {
var Chapter = {
Title: chapterItem.name,
NR: chapterItem.chap_number,
URL: chapterItem.src,
MangaID: mangaItem.MangaID,
MangaName: mangaItem.Title,
VolumeNR: chapterItem.volume
};
sql_insertInto("Chapters", Chapter, function (insertError, insertResult) {
if(!insertError){
var insertedChapter =
"------------------------------------------------------------------------\n" +
" Added new Chapter: " + Chapter.NR + " For: " + mangaItem.Title + "\n" +
"------------------------------------------------------------------------\n";
callback(null,insertedChapter ,insertResult);
}
else{
if(insertError.code === "ER_DUP_ENTRY") {
var dupEntry = "------------------------------------------------------------------------\n" +
" Duplicate Entry: Chapter: " + Chapter.NR + " For: " + mangaItem.Title + "\n" +
"------------------------------------------------------------------------\n"
callback(null, dupEntry, null);
}
else{
callback(insertError, null, null);
}
}
})
})
})
.catch(fetchChapterError => {
callback(fetchChapterError, null, null);
})
})
}
else{
callback(selectError, null, null);
}
});
}`
我真的不知道如何解决这个问题,因为我不确定问题是什么:
非常感谢你,我感谢你能得到的每一个帮助。
编辑:
function sql_selectAll(tableName, callback){
var sql = 'SELECT * FROM `' + tableName + '`';
connection.query(sql, function (err, selectAllResult) {
callback(err, selectAllResult);
})
}
function sql_insertInto(tableName, insertionObject, callback) {
var sql = 'insert into ' + tableName + ' set ?';
connection.query(sql, insertionObject, function (err, insertResult) {
callback(err, insertResult);
});
}
答案 0 :(得分:0)
您正在同时为每个SQL结果调用mangafox端点,而不是一次调用一个或以块为单位。您可以尝试使用async/await
。我不熟悉您正在使用的sql API,但假设方法sql_selectAll
和sql_insertInto
返回promises如果没有给出回调,您可以将函数重写为像这样的东西:
async function insertChapters(callback) {
try {
const mangas = await sql_selectAll("Mangas");
for (const mangaItem of mangas) {
const chapters = await gin.mangafox.chapters(mangaItem.Title);
for (const chapterItem of chapters) {
const Chapter = {
Title: chapterItem.name,
NR: chapterItem.chap_number,
URL: chapterItem.src,
MangaID: mangaItem.MangaID,
MangaName: mangaItem.Title,
VolumeNR: chapterItem.volume
};
try {
const insertResult = await sql_insertInto("Chapters", Chapter);
const insertedChapter =
"------------------------------------------------------------------------\n" +
" Added new Chapter: " + Chapter.NR + " For: " + mangaItem.Title + "\n" +
"------------------------------------------------------------------------\n";
callback(null, insertedChapter, insertResult);
} catch (error) {
if (error.code === "ER_DUP_ENTRY") {
const dupEntry = "------------------------------------------------------------------------\n" +
" Duplicate Entry: Chapter: " + Chapter.NR + " For: " + mangaItem.Title + "\n" +
"------------------------------------------------------------------------\n";
callback(null, dupEntry, null);
} else {
throw error;
}
}
}
}
} catch (error) {
callback(error, null, null);
}
}
注意await
个关键字 - 这些关键字在async function
中是允许的,并且基本上告诉JS引擎暂停异步函数的执行,并在等待的承诺结算之前执行其他操作。
另请注意,在使用try
关键字处理承诺时,您可以使用常规的旧式catch
/ await
块!我没有做任何特殊处理fetchChapterError
的事情,因为它将由最外面的catch
块处理!此外,对于插入错误,如果它不是重复条目,我们可以重新抛出错误,并让它也被最外面的catch块捕获。
如果你的SQL函数没有返回promises,那么在Node version 8(最新版本)上你可以使用util.promisify
:
const util = require('util');
sql_selectAll = util.promisify(sql_selectAll);
如果你没有使用Node 8,那么你可以使用另一个promisify
实现(例如,查看bluebird),或者你可以很容易地编写自己的(阅读关于promises的MDN文章) )。