我正在尝试通过await / async以顺序/同步顺序执行以下逻辑。
async loadData() {
console.log("STEP 1");
let ratesResponse = await getRates();
let accounts = realm.objects("Account");
accounts.map(async account => {
let accountResponse = await getAccountBalance(account.accountid);
console.log("STEP 2");
realm.write(() => {
account.cad_balance = accountResponse.balances[0].value;
account.usd_balance = (
parseFloat(accountResponse.balances[0].value) *
parseFloat(ratesResponse.last)
).toString();
});
});
console.log("STEP 3");
this.setState({
data: realm.objects("Account"),
last: ratesResponse.last,
high: ratesResponse.high,
low: ratesResponse.low,
refreshing: false
});
}
但是,应用功能不起作用,并且日志确认在步骤2之前发生的步骤3:
2018-02-22 22:53:10.922 [info][tid:com.facebook.react.JavaScript] STEP 1
2018-02-22 22:53:10.921822-0500[13978:3180532] STEP 1
2018-02-22 22:53:11.211 [info][tid:com.facebook.react.JavaScript] STEP 3
2018-02-22 22:53:11.210787-0500[13978:3180532] STEP 3
2018-02-22 22:53:11.233 [info][tid:com.facebook.react.JavaScript] STEP 2
2018-02-22 22:53:11.233529-0500[13978:3180532] STEP 2
我错过了什么?
答案 0 :(得分:2)
首先 - 您需要等待accounts.map(async account => {...})
这可以使用await Promise.all来实现...即
Promise.all(accounts.map(async account => {...}))
其次,如果realm.write是异步,则需要等待在该函数完成时解析的Promise
await new Promise(resolve => realm.write(resolve));
所以,把它们放在一起
async function loadData() {
console.log('STEP 1');
let ratesResponse = await getRates();
let accounts = realm.objects('Account');
await Promise.all(accounts.map(async account => {
let accountResponse = await getAccountBalance(account.accountid);
console.log('STEP 2');
await new Promise(resolve => realm.write(resolve));
account.cad_balance = accountResponse.balances[0].value;
account.usd_balance = (parseFloat(accountResponse.balances[0].value) * parseFloat(ratesResponse.last)).toString();
}));
console.log('STEP 3');
this.setState({
data: realm.objects('Account'),
last: ratesResponse.last,
high: ratesResponse.high,
low: ratesResponse.low,
refreshing: false
});
}
答案 1 :(得分:1)
Array.prototype.map
没有等待提供的函数,因此在Array.prototype.map
提供的函数内等待不会导致您期望的同步行为。
您有两个选择
使用在块中考虑for in
的原生await
运算符,例如
async loadData(){
console.log("STEP 1");
let ratesResponse = await getRates();
let accounts = realm.objects("Account");
for (let account in accounts) {
let accountResponse = await getAccountBalance(account.accountid);
console.log("STEP 2");
realm.write(() => {
account.cad_balance = accountResponse.balances[0].value;
account.usd_balance = (
parseFloat(accountResponse.balances[0].value) *
parseFloat(ratesResponse.last)
).toString();
});
}
console.log("STEP 3");
this.setState({
data: realm.objects("Account"),
last: ratesResponse.last,
high: ratesResponse.high,
low: ratesResponse.low,
refreshing: false
});
}
或等待async函数返回的承诺列表,如
async loadData(){
console.log("STEP 1");
let ratesResponse = await getRates();
let accounts = realm.objects("Account");
await Promise.all(accounts.map(async (account) => {
let accountResponse = await getAccountBalance(account.accountid);
console.log("STEP 2");
realm.write(() => {
account.cad_balance = accountResponse.balances[0].value;
account.usd_balance = (
parseFloat(accountResponse.balances[0].value) *
parseFloat(ratesResponse.last)
).toString();
});
});
console.log("STEP 3");
this.setState({
data: realm.objects("Account"),
last: ratesResponse.last,
high: ratesResponse.high,
low: ratesResponse.low,
refreshing: false
});
}
然而,这两者将如何运作存在微妙的差异,第一个将逐个处理每个帐户,而第二个将并行处理所有帐户,但在继续之前等待并行执行完成。
答案 2 :(得分:0)
accounts.map(async() => ({}))
返回一系列承诺。
然后,您需要将该数组传递给Promise.all()
和await
。
一旦该阵列中的所有承诺解决了,它就会执行下一个console.log('STEP 3')
。
async function loadData() {
console.log('STEP 1')
const ratesResponse = await getRates()
const accounts = realm.objects('Account')
const promises = accounts.map(async (account) => {
const accountResponse = await getAccountBalance(account.accountid)
console.log('STEP 2')
realm.write(() => {
account.cad_balance = accountResponse.balances[0].value
account.usd_balance = (
parseFloat(accountResponse.balances[0].value) *
parseFloat(ratesResponse.last)
).toString()
})
})
await Promise.all(promises)
console.log('STEP 3')
this.setState({
data: realm.objects('Account'),
last: ratesResponse.last,
high: ratesResponse.high,
low: ratesResponse.low,
refreshing: false,
})
}