for循环内的回调函数 - Nodejs

Callback function inside for loop - Nodejs

祝您今天过得愉快。我最近发现在 for 循环中处理回调并不容易。我尝试了一些事情,但找不到解决方案。 这是代码:

var book = new Array;
var chapters = Object.keys(epub.spine.contents).length;

for (let i = 0; i < chapters; i++) {
    let cacheArray = [];
    epub.getChapter(epub.spine.contents[i].id, function (err, data) {
        if (err) {
            return console.log(err);
        }
        //remove html tags
        let str = data.replace(/<\/?[\w\s]*>|<.+[\W]>/g, '');
        book.push(str)
    })
}
console.log(book)//returns empty array ofc

执行此代码后,我需要遍历数组以搜索其内容。如果不是这种情况,我的方法是将其发送到数据库。

我的方法如下:

var recursiveChapter = function (n) {
    var book = new Array;
    if (n < chapters) {
        // chapter function
        epub.getChapter(epub.spine.contents[n].id, function (err, data) {
            if (err) {
                throw err
            }
            //remove HTML tags
            let str = data.replace(/<\/?[\w\s]*>|<.+[\W]>/g, '');
            book.push(str)
            recursiveChapter(n + 1)
        });
    }
}
//start the recursive function
recursiveChapter(0)
console.log(book)//returns an empty array

我被卡住了,想不出不将其存储在数据库中就可以使用这些数据的方法。 任何帮助将不胜感激。

有几种方法可以解决这个问题。一种方法是使用 async library,这允许 运行 异步。并行或串行调用。

例如,我们可以使用async.mapSeries()将一系列异步调用的结果作为数组获取。

您输入您的 ID 数组,然后回调将 return 数据数组 returned,例如,我模拟了 getChapter() 函数来给您一个关于它如何工作的想法:

// Mock out epub object
const epub = { 
    getChapter(id, callback) {
        setTimeout(() => callback(null, "Data for id " + id), 250);
    }
}

let ids = [1,2,3,4];
console.log("Calling async.mapSeries for ids:", ids);
async.mapSeries(ids, epub.getChapter, (err, result) => {
    if (err) {
        console.error(err);
    } else {
        console.log("Result:", result)
    }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/async/3.2.0/async.min.js" integrity="sha512-6K6+H87tLdCWvY5ml9ZQXLRlPlDEt8uXmtELhuJRgFyEDv6JvndWHg3jadJuBVGPEhhA2AAt+ROMC2V7EvTIWw==" crossorigin="anonymous"></script>

您也可以承诺 epub 调用并使用 Promise.all 获取结果,如下所示:

epub = { 
    getChapter(id, callback) {
        setTimeout(() => callback(null, "Data for id " + id), 250);
    }
}
 
let ids = [1,2,3,4];

function getChapterPromisified(id) {
    return new Promise((resolve, reject) => { 
        epub.getChapter(id, (err, data) => { 
            if (err) {
                reject(err);
            } else {
                resolve(data);
            }
        })
    })
}

// Create a list of promises, one for each call
const promises = ids.map(id => getChapterPromisified(id))
Promise.all(promises)
    .then(result => console.log("Result:", result))
    .catch(error => console.error("An error occurred:", err));