最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React Native: Chain Async Calls. e.g to AsyncStorage? - Stack Overflow

programmeradmin2浏览0评论

I'm trying to chain several calls to AsyncStorage.getItem() but cannot seem to get the calls to trigger in the correct order. I seem to manage to drop out of the loop with the last item pleted before earlier items. It appears that React uses a different syntax for promises than how jQuery would work.

In this example I am trying to chain calls to get vars v1, v2, v3. v3 triggers a refresh of the UI for which vars v1 and v2 are required. My code for two chained vars is as follows:

AsyncStorage.getItem("v1")
.then(
    (value) => {
        if (value !== null){
            varCollection.v1 =value
        }
    }
)
.then( () => {
    AsyncStorage.getItem("v3")
    .then((value) => {
        if (value !== null){
            varCollection.v3 = value;
        }else{
            varCollection.v3 = "default value";
        }
    })
    .done()
})
.done();

This appears to work but it may be simply luck that causing it to work as when I add another link to the chain, things go wrong.

AsyncStorage.getItem("v1")
.then(
    (value) => {
        if (value !== null){
            varCollection.v1 =value
        }
    }
)
.then( () => {
    AsyncStorage.getItem("v2")
    .then((value) => {
        if (value !== null){
            varCollection.v2 = value;
        }
    })
    .done()
})
.then( () => {
    AsyncStorage.getItem("v3")
    .then((value) => {
        if (value !== null){
            varCollection.v3 = value;
        }else{
            varCollection.v3 = "default value";
        }
    })
    .done()
})
.done();

This results in v3 altering and triggering the state of the app to change even though v2 may not have been assigned yet.

Calling console.log() on each of the vars in props.varCollection from getInitialState() of child elements shows v1 is present but v2 isn't or vice versa. I have also tried nesting my calls to create the chain which I realised gets messy quickly.

* Update * Further to SLacks and Bergi's suggestions I have also tried the following:

AsyncStorage.getItem("v1")
.then((value) => {
    if (value !== null){
        v1 = value;
    }
})
.then( () =>{
    return( 
        AsyncStorage.getItem("v2")
        .then((value) => {
            if (value !== null){
                v2 = value;
            }
        })
    )
})
.then( () => {
    return(
        AsyncStorage.getItem("v3")
        .then((value) => {
            if (value !== null){
                v3 = value;
            }
        })
    )
})
.done();

and

AsyncStorage.getItem("v1")
.then((value) => {
    if (value !== null){
        v1 = value;
    }
})
.then( () =>
    ( 
        AsyncStorage.getItem("v2")
        .then((value) => {
            if (value !== null){
                v2 = value;
            }
        })
    )
)
.then( () => 
    (
        AsyncStorage.getItem("v3")
        .then((value) => {
            if (value !== null){
                v3 = value;
            }
        })
    )
)
.done();

but still get stuck at the second call.

* /Update *

What is the correct way to chain Async calls in React Native?

I'm trying to chain several calls to AsyncStorage.getItem() but cannot seem to get the calls to trigger in the correct order. I seem to manage to drop out of the loop with the last item pleted before earlier items. It appears that React uses a different syntax for promises than how jQuery would work.

In this example I am trying to chain calls to get vars v1, v2, v3. v3 triggers a refresh of the UI for which vars v1 and v2 are required. My code for two chained vars is as follows:

AsyncStorage.getItem("v1")
.then(
    (value) => {
        if (value !== null){
            varCollection.v1 =value
        }
    }
)
.then( () => {
    AsyncStorage.getItem("v3")
    .then((value) => {
        if (value !== null){
            varCollection.v3 = value;
        }else{
            varCollection.v3 = "default value";
        }
    })
    .done()
})
.done();

This appears to work but it may be simply luck that causing it to work as when I add another link to the chain, things go wrong.

AsyncStorage.getItem("v1")
.then(
    (value) => {
        if (value !== null){
            varCollection.v1 =value
        }
    }
)
.then( () => {
    AsyncStorage.getItem("v2")
    .then((value) => {
        if (value !== null){
            varCollection.v2 = value;
        }
    })
    .done()
})
.then( () => {
    AsyncStorage.getItem("v3")
    .then((value) => {
        if (value !== null){
            varCollection.v3 = value;
        }else{
            varCollection.v3 = "default value";
        }
    })
    .done()
})
.done();

This results in v3 altering and triggering the state of the app to change even though v2 may not have been assigned yet.

Calling console.log() on each of the vars in props.varCollection from getInitialState() of child elements shows v1 is present but v2 isn't or vice versa. I have also tried nesting my calls to create the chain which I realised gets messy quickly.

* Update * Further to SLacks and Bergi's suggestions I have also tried the following:

AsyncStorage.getItem("v1")
.then((value) => {
    if (value !== null){
        v1 = value;
    }
})
.then( () =>{
    return( 
        AsyncStorage.getItem("v2")
        .then((value) => {
            if (value !== null){
                v2 = value;
            }
        })
    )
})
.then( () => {
    return(
        AsyncStorage.getItem("v3")
        .then((value) => {
            if (value !== null){
                v3 = value;
            }
        })
    )
})
.done();

and

AsyncStorage.getItem("v1")
.then((value) => {
    if (value !== null){
        v1 = value;
    }
})
.then( () =>
    ( 
        AsyncStorage.getItem("v2")
        .then((value) => {
            if (value !== null){
                v2 = value;
            }
        })
    )
)
.then( () => 
    (
        AsyncStorage.getItem("v3")
        .then((value) => {
            if (value !== null){
                v3 = value;
            }
        })
    )
)
.done();

but still get stuck at the second call.

* /Update *

What is the correct way to chain Async calls in React Native?

Share edited May 29, 2015 at 16:07 Moss Palmer asked May 29, 2015 at 15:02 Moss PalmerMoss Palmer 1,8541 gold badge16 silver badges31 bronze badges 2
  • 1 You need to return the promises to the chain. – SLaks Commented May 29, 2015 at 15:05
  • How would I do that? – Moss Palmer Commented May 29, 2015 at 15:05
Add a ment  | 

3 Answers 3

Reset to default 6

I'm not sure why the suggested syntax from Bergi did not work but I found that separating the call and assignment before and after the then statement allowed strict control of ordering and that the return statement should only return the promise from the last call in each block. This may not be the best way to do it, but it seems to work quite well for sequential synchronous reads.

AsyncStorage.getItem("v1")
.then( (value) =>
      {
        this.setState({v1:value})
        return AsyncStorage.getItem("v2")
      }
)
.then( (value) =>
    {
        this.setState({v2: value})
        return AsyncStorage.getItem("v3")
    }
)
.then( (value) =>
    {
        this.setState({v3:value})
        return AsyncStorage.getItem("v4")
    }
)
.then( (value) =>
    {
        return this.setState({v4:value})
    }
).done();

You can see it in action at https://rnplay/plays/51t0cQ

You need to return those promises from the then callbacks. Just put a return statement in front of each, or omit the block braces of your arrow function.

Then you also will only need one single .done() in the end.

Update: React native supports es7 async await now.
So you can do something like this now,

let x = await <Promisified/async functions>
let y = //use x 

and don't forget to wrap then in try,catch ;)

发布评论

评论列表(0)

  1. 暂无评论