在本机反应中获取返回旧数据的 API

Posted

技术标签:

【中文标题】在本机反应中获取返回旧数据的 API【英文标题】:Fetch API returning old data in react native 【发布时间】:2018-04-10 07:17:15 【问题描述】:

说明: 我正在制作一个反应原生应用程序,其中有一个我正在关注的 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 工作成功,也就是修改了以下数据。但是,在我的应用程序中,fetchunfollow 之前返回相同的旧数据,即使 github 网站 UI 显示更改并且 Postman 返回新的修改数据。 我也稍微更新了代码。

代码

以下列表

    /**
     * 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 助手

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;
        
    ,

【问题讨论】:

GithubApi.unfollow_user() 看起来像什么? / 什么是this.state.login @ArmanCharan,抱歉,我刚刚更新了代码 sn-p 以包含 unfollower_userthis.state.login 只是用户的 github 登录用户名。 好兄弟。您的意思是将您的GithubApi 对象定义为Class?我以前从未真正见过有人在这样的对象上调用this 您可能还想尝试template literals 来构建您的 HTTP 请求。 是的,我以后肯定会重构。我只是想解决这个问题。 【参考方案1】:

试试这个:

let response = await fetch(url, 
  headers: 
    'Cache-Control': 'no-cache'
  
);

【讨论】:

【参考方案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 在此函数内部有一个值,但在外部未定义。

【讨论】:

【参考方案3】:

您在_get_data_from_github_with_firebase 中缺少await。 尝试将函数更改为:

_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 来同步操作。

【讨论】:

感谢您的意见,但这也不起作用。结果也返回未定义。

以上是关于在本机反应中获取返回旧数据的 API的主要内容,如果未能解决你的问题,请参考以下文章

React Native Fetch API json返回旧数据

如何在本机反应中更改获取响应的按钮文本?

如何在本机反应中从 json 获取数据?

GPS位置在本机反应中波动

反应本机 firebase 实时数据库参考返回 null

阿波罗客户端在反应原生的初始重新加载中返回未定义