描述: 我正在做一个本机应用程序,我有一个我正在关注的github用户列表,我想实现取消关注和刷新列表的功能。
我制作了两个异步助手来与github API进行交互,一个用于取消关注用户(通过PUT),另一个用于获取以下列表(通过GET)。我还在以下组件列表中添加了一个firebase侦听器。以下每个人都会将我导航到一个由取消关注按钮组成的个人资料视图。单击按钮时,它应取消关注用户,更新组件中的以下列表,然后导航回以下组件列表。
问题 取消关注用户正在按预期工作,但以下列表视图仍包含旧列表。我的代码返回旧数据,即使github api正在返回新的更新数据,所以我怀疑问题必须是我使用async / await的方式。
我甚至创建了一个刷新按钮来刷新以下列表,但有时会返回新数据,例如1/20次。
更新:测试多个方案后,我认为firebase不是问题,因为fetch
返回相同的旧数据。我认为主要问题可能在于fetch
电话。我已经测试了从Postman获取数据并且它抓取了正确的数据。
由于fetch
包含旧数据,response.json()
似乎没有按预期工作。我在这里做了一个简单的jsfiddle(你需要提供自己的访问令牌),显示get_following -> unfollow -> get_following
成功运行,也就是修改了以下数据。但是,在我的应用程序中,fetch
在unfollow
之前返回相同的旧数据,即使github网站UI显示更改而邮递员返回新修改的数据。
我还稍微更新了代码。
代码
以下列表
/**
* Listens for any changes on the database and updates the
* dataSource accordingly.
* @param {Firebase Object} ref
*/
_listenForData(ref) {
ref.on('value', (snapshot) => {
this.setState({
dataSource: snapshot.val()
},
this.setState({
isLoading: false,
}));
});
}
componentDidMount() {
// Sets up the listener for realtime changes.
GithubApi.get_followings(this.ref)
.then(_ => this._listenForData(this.ref));
}
具有取消关注按钮的个人用户
async unfollow() {
try {
let success = await GithubApi.unfollow_user(this.state.login);
console.log('unfollowed user');
console.log(success);
if (success) {
// Updates database after unfollowing
console.log('update followings')
await GithubApi.get_followings(this.ref);
return true;
}
} catch (error) {
console.error(error);
return false;
}
}
render() {
const { goBack } = this.props.navigation;
return (
<Button
title='Unfollow'
onPress={
() => this.unfollow().then(_ => goBack())
}
/>
)
}
Github Api Helpers
const GithubApi = {
url: 'https://api.github.com/',
access_token: ...,
/**
* An asychronous helper function to grab data from github
* given an url and add data the firebase.
*
* @param {string} url
* @param {Firebase Object} firebaseRef
*/
_get_data_from_github_with_firebase: async function(url, firebaseRef) {
try {
let response = await fetch(url);
let responseStatus = await response.status;
let responseJson = await response.json();
if (responseStatus === 200) {
firebaseRef.set(responseJson,
(error) => {
if (error) {
console.log(error);
return false;
} else {
return true;
}
});
}
return false;
} catch (error) {
return false;
}
},
/**
* Gets the user's following data and adds it to the database.
* @param {Firebase Object} firebaseRef
*/
get_followings: async function(firebaseRef) {
return await this._get_data_from_github_with_firebase(
this.url + 'user/following?' + this.access_token,
firebaseRef
);
},
unfollow_user: async function(username) {
try {
let url = this.url + 'user/following/' + username + '?' + this.access_token;
let response = await fetch(url, { method: 'DELETE'});
let responseStatus = await response.status;
if (responseStatus === 204) {
return true;
}
return false;
} catch (error) {
return false;
}
},
答案 0 :(得分:2)
await
内缺少_get_data_from_github_with_firebase
。
尝试将功能更改为:
_get_data_from_github_with_firebase: async function(url, firebaseRef) {
try {
let response = await fetch(url);
let responseStatus = await response.status;
let responseJson = await response.json();
var result = false
if (responseStatus === 200) {
result = await firebaseRef.set(responseJson,
(error) => {
if (error) {
console.log(error);
return false;
} else {
return true;
}
});
}
return result;
} catch (error) {
return false;
}
},
注意我强烈建议您使用redux-saga来同步操作。
答案 1 :(得分:2)
您是否曾经是前C开发人员?或者您习惯通过引用传递变量?
我认为你的问题是在这个函数中你试图通过引用返回一个值:
_get_data_from_github_with_firebase: async function(url, firebaseRef) {
try {
let response = await fetch(url);
let responseStatus = await response.status;
let responseJson = await response.json();
var result = false
if (responseStatus === 200) {
result = await firebaseRef.set(responseJson, //You are executing a method by reference
(error) => {
if (error) {
console.log(error);
return false;
} else {
return true;
}
});
}
return result;
} catch (error) {
return false;
}
},
也许更专业的JS开发人员可以确认这是否可行,但我不习惯这样做。我会改变签名,只返回responseJson,而不是试图像这样设置它。
可能responseJson在此函数中有一个值,但在外部未定义。
答案 2 :(得分:0)
尝试一下,
let response = await fetch(url{
headers: {
'Cache-Control': 'no-cache'
}
});