如何使用承诺和递归通过 Facebook Graph API 检索用户的所有帖子?
How to retrieve all posts of a user via Facebook Graph API using promises and recursion?
我目前正在开发一个使用 Facebook Graph 的网络应用 API。
我想要实现的是获取一个用户的所有post。
但是,这并不容易,因为我必须对结果进行分页。
此刻我正在为承诺而苦苦挣扎。
我试图实现的是用 post 个对象填充一个数组。
因此我使用了无法按预期工作的承诺和递归。
我的代码目前如下所示:
// Here I retrieve the user with his or her posts,
// just the first 25 due to pagination
if (accessToken) {
return new Promise(resolve => {
FB.api('/me?fields=id,name,posts&access_token=' + accessToken, response => {
this.get('currentUser').set('content', response);
resolve()
})
})
}
// Returns all posts of a given user
function getAllPostsOfUser(posts, postsArr) {
// Process each post of the current pagination level
for (var post of posts.data) {
// Only store meaningful posts
if (post !== undefined && post.message !== undefined) {
postsArr.push(post)
}
}
// Further posts are retrievalable via paging.next which is an url
if (posts.data.length !== 0 && posts.paging.next !== undefined) {
FB.api(posts.paging.next, response => {
getAllPostsOfUser(response, postsArr)
resolve()
})
}
return postsArr
}
var posts = getAllPostsOfUser(this.get('currentUser').content.posts, [])
// I want to use all the posts here
console.log(posts)
我遇到的问题是我想在放置 console.log 的地方使用 posts 但是当我记录 posts 数组时很多 post 不见了。
我确信我做错了承诺,但我不知道是什么。
如果有人能指导我找到解决方案,我会很高兴。
提前致谢。
试试这个:
function getAllPosts() {
return new Promise((resolve, reject) => {
let postsArr = [];
function recursiveAPICall(apiURL) {
FB.api(apiURL, (response) => {
if (response && response.data) {
//add response to posts array (merge arrays), check if there is more data via paging
postsArr = postsArr.concat(response.data);
if (response.paging && response.paging.next) {
recursiveAPICall(response.paging.next);
} else {
resolve(postsArr);
}
} else {
reject();
}
});
}
recursiveAPICall("/me/posts?fields=message&limit=100");
});
}
getAllPosts()
.then((response) => {
console.log(response);
})
.catch((e) => {
console.log(e);
});
未经测试,只是我想出的一个简单示例。它 returns 一个承诺并使用递归函数来获取所有条目。顺便说一句,您不需要添加访问令牌。如果您已登录,SDK 将在内部使用它。
这是一个已经回答过的老问题,但考虑到可以节省多少行代码,我认为它可以使用更现代的答案。此代码尚未在真实 API 中进行测试,但它应该可以工作。
此函数returns 一系列帖子的承诺。
async function getPosts(url = "/me/posts?fields=message&limit=100") {
const { error, paging, data } = (await new Promise(r => FB.api(url, r))) || {}
if (error || !data) throw new Error(error || "Could not get posts")
return data.concat(paging.next ? await getPosts(paging.next) : [])
}
有评论:
async function getPosts(url = "/me/posts?fields=message&limit=100") {
// get response data out of callback
const { error, paging, data } = (await new Promise(r => FB.api(url, r))) || {}
// if there was an error or there wasn't any data, throw
if (error || !data) throw new Error(error || "Could not get posts")
// return this page's data + if there's a next page, recursively get its data
return data.concat(paging?.next ? await getPosts(paging.next) : [])
}
然后可以像这样使用函数:
async function main() {
try {
const posts = await getPosts(); // the array of posts
console.log(posts);
} catch (error) {
console.error(error);
}
}
main();
下面是使用假 API.
演示函数的片段
// fake api for testing purposes
const FB = {
api(url, callback) {
const pages = [
{
data: ["post1", "post2", "post3"],
paging: { next: 1 },
},
{
data: ["post4", "post5", "post6"],
paging: { next: 2 },
},
{
data: ["post7", "post8", "post9"],
},
];
if (typeof url !== "number") return callback(pages[0]);
return callback(pages[url]);
},
};
async function getPosts(url = "/me/posts?fields=message&limit=100") {
const { error, paging, data } = (await new Promise(r => FB.api(url, r))) || {}
if (error || !data) throw new Error(error || "Could not get posts")
return data.concat(paging.next ? await getPosts(paging.next) : [])
}
async function main() {
try {
const posts = await getPosts(); // the array of posts
console.log(posts);
} catch (error) {
console.error(error);
}
}
main();
.as-console-wrapper{max-height:none !important;top: 0;}
我目前正在开发一个使用 Facebook Graph 的网络应用 API。
我想要实现的是获取一个用户的所有post。
但是,这并不容易,因为我必须对结果进行分页。
此刻我正在为承诺而苦苦挣扎。
我试图实现的是用 post 个对象填充一个数组。
因此我使用了无法按预期工作的承诺和递归。
我的代码目前如下所示:
// Here I retrieve the user with his or her posts,
// just the first 25 due to pagination
if (accessToken) {
return new Promise(resolve => {
FB.api('/me?fields=id,name,posts&access_token=' + accessToken, response => {
this.get('currentUser').set('content', response);
resolve()
})
})
}
// Returns all posts of a given user
function getAllPostsOfUser(posts, postsArr) {
// Process each post of the current pagination level
for (var post of posts.data) {
// Only store meaningful posts
if (post !== undefined && post.message !== undefined) {
postsArr.push(post)
}
}
// Further posts are retrievalable via paging.next which is an url
if (posts.data.length !== 0 && posts.paging.next !== undefined) {
FB.api(posts.paging.next, response => {
getAllPostsOfUser(response, postsArr)
resolve()
})
}
return postsArr
}
var posts = getAllPostsOfUser(this.get('currentUser').content.posts, [])
// I want to use all the posts here
console.log(posts)
我遇到的问题是我想在放置 console.log 的地方使用 posts 但是当我记录 posts 数组时很多 post 不见了。
我确信我做错了承诺,但我不知道是什么。
如果有人能指导我找到解决方案,我会很高兴。
提前致谢。
试试这个:
function getAllPosts() {
return new Promise((resolve, reject) => {
let postsArr = [];
function recursiveAPICall(apiURL) {
FB.api(apiURL, (response) => {
if (response && response.data) {
//add response to posts array (merge arrays), check if there is more data via paging
postsArr = postsArr.concat(response.data);
if (response.paging && response.paging.next) {
recursiveAPICall(response.paging.next);
} else {
resolve(postsArr);
}
} else {
reject();
}
});
}
recursiveAPICall("/me/posts?fields=message&limit=100");
});
}
getAllPosts()
.then((response) => {
console.log(response);
})
.catch((e) => {
console.log(e);
});
未经测试,只是我想出的一个简单示例。它 returns 一个承诺并使用递归函数来获取所有条目。顺便说一句,您不需要添加访问令牌。如果您已登录,SDK 将在内部使用它。
这是一个已经回答过的老问题,但考虑到可以节省多少行代码,我认为它可以使用更现代的答案。此代码尚未在真实 API 中进行测试,但它应该可以工作。
此函数returns 一系列帖子的承诺。
async function getPosts(url = "/me/posts?fields=message&limit=100") {
const { error, paging, data } = (await new Promise(r => FB.api(url, r))) || {}
if (error || !data) throw new Error(error || "Could not get posts")
return data.concat(paging.next ? await getPosts(paging.next) : [])
}
有评论:
async function getPosts(url = "/me/posts?fields=message&limit=100") {
// get response data out of callback
const { error, paging, data } = (await new Promise(r => FB.api(url, r))) || {}
// if there was an error or there wasn't any data, throw
if (error || !data) throw new Error(error || "Could not get posts")
// return this page's data + if there's a next page, recursively get its data
return data.concat(paging?.next ? await getPosts(paging.next) : [])
}
然后可以像这样使用函数:
async function main() {
try {
const posts = await getPosts(); // the array of posts
console.log(posts);
} catch (error) {
console.error(error);
}
}
main();
下面是使用假 API.
演示函数的片段// fake api for testing purposes
const FB = {
api(url, callback) {
const pages = [
{
data: ["post1", "post2", "post3"],
paging: { next: 1 },
},
{
data: ["post4", "post5", "post6"],
paging: { next: 2 },
},
{
data: ["post7", "post8", "post9"],
},
];
if (typeof url !== "number") return callback(pages[0]);
return callback(pages[url]);
},
};
async function getPosts(url = "/me/posts?fields=message&limit=100") {
const { error, paging, data } = (await new Promise(r => FB.api(url, r))) || {}
if (error || !data) throw new Error(error || "Could not get posts")
return data.concat(paging.next ? await getPosts(paging.next) : [])
}
async function main() {
try {
const posts = await getPosts(); // the array of posts
console.log(posts);
} catch (error) {
console.error(error);
}
}
main();
.as-console-wrapper{max-height:none !important;top: 0;}