处理彼此需要数据的嵌套异步函数的最佳方法是什么?

时间:2019-05-18 01:56:38

标签: javascript mysql node.js asynchronous

我有一个网站,该网站的用户页面具有以下关系:

  • 用户页面需要一个“发布”对象列表。
  • 发布对象需要一个“媒体”字符串列表(按“字符串”,我的意思是我只需要特定列中的标题字符串字段)。

帖子对象和媒体字符串对象都是从我的数据库中获得的,这意味着我需要先查询与用户ID匹配的帖子,然后再查询与每个帖子对象匹配的媒体对象。

我的主要问题是:如何重新格式化当前代码(如下)以支持上述功能?

我没有尝试太多,因为我什至不知道从哪里开始。我的第一个尝试是将查询隔离到它们自己的异步函数中,然后我可以等待它们,但是这引发了诸如“等待仅在异步函数中有效”之类的错误。我也研究了诺言,但一切都超过了我。

我当前的代码显示了我的函数方法,在这里我第一次调用以获取所有相关的帖子(users [0]是由用户指定的输入查询的用户对象):

// I pass this to handlebars for partial renders
let posts = getPostsForUser(users[0].user_id);

和我的查询函数是这样定义的:

function getPostsForUser(uid) {
    pool.query('SELECT post_id, body, date_time FROM Post WHERE Post.author = ?', [uid], (err, result) => {         
        if (result.length) {
            let posts = [];

            // Put all posts into the posts array
            for (i = 0; i < result.length; i++) {
                let subs = getMediaForPost(result[i].post_id);
                posts.push({
                    "postContent": result[i].body,
                    "timestamp": result[i].date_time,
                    "subjects": subs
                });
            }

            return posts;
        } else return [];
    });
}

function getMediaForPost(pid) {
    // Returns an array of media objects queried to match the given pid
    pool.query('SELECT title FROM Media WHERE media_id IN (SELECT media_id FROM Post_Media WHERE post_id = ?)', [pid], (err, result) => {
        if (result.length) {
            let postMedia = [];

            for (i = 0; i < result.length; i++)
                postMedia.push({"postSubject": result[i].title});

            return postMedia;
        } else return [];
    });
}

我所有的查询都为我提供了正确的信息,我只是不知道如何在呈现用户页面之前等待上述查询完成。

最后,“帖子”应包含一个“帖子”对象数组,每个“帖子”对象应包含一个与数据库中与用户匹配的“媒体对象”数组。

1 个答案:

答案 0 :(得分:0)

尝试

let posts = await getPostsForUser(users[0].user_id);

function getPostsForUser(uid) {
    return new Promise((resolve, reject) => {
        return pool.query('SELECT post_id, body, date_time FROM Post WHERE Post.author = ?', [uid], async (err, result) => {
            if (err) return reject(err);
            if (result.length) {
                let posts = [];

                // Put all posts into the posts array
                for (i = 0; i < result.length; i++) {
                    let subs = await getMediaForPost(result[i].post_id);
                    posts.push({
                        "postContent": result[i].body,
                        "timestamp": result[i].date_time,
                        "subjects": subs
                    });
                }
                return resolve(posts);
            } else return resolve([]);
        });
    })

}

function getMediaForPost(pid) {
    // Returns an array of media objects queried to match the given pid
    return new Promise((resolve, reject) => {
        return pool.query('SELECT title FROM Media WHERE media_id IN (SELECT media_id FROM Post_Media WHERE post_id = ?)', [pid], (err, result) => {
            if (err) return reject(err);
            if (result.length) {
                let postMedia = [];

                for (i = 0; i < result.length; i++)
                    postMedia.push({ "postSubject": result[i].title });

                return resolve(postMedia);
            } else return resolve([]);
        });
    });
}

这样,您可以使用由回调传递的数据,因为您无法在回调中使数据返回到函数中,可以使用promise,并且可以在没有回调的情况下使用promise在您范围内的其他地方使用变量可以使用等待/异步。

注意:这将阻止循环并执行任务。

了解有关等待/异步的更多信息 Here And Here

编辑:发生错误await is only valid in async function是因为您必须在函数名称前添加async

相关问题