我的目标是通过调用_addStock()
中的componentDidMount
函数,在组件状态中添加一个新的股票 - 包括报价,图表,元信息到各自的数组中。但是,在循环并调用_addStock
之后,我在每个相应的数组中只有1个库存。
我可以通过在每个_addStock
调用之间通过setTimeouts添加延迟来实现此功能 - 但这会违背承诺的目的。
setState
时,_addStock
似乎只被调用一次。
发生了什么?
_fetchMeta
,_fetchQuote
,...等返回承诺。
...
// this is what my state ends up looking like, only 1 per key when I'm expecting 4.
this.state = {
stocks: [
{
symbol: 'MSFT',
display: '...',
color: '...'
}
],
metas: [
{
symbol: 'MSFT',
name: '...',
description: '...'
}
],
quotes: [
{
symbol: 'MSFT',
price: '...',
change: '...'
}
],
charts: [
{
symbol: 'MSFT',
data: "..."
}
]
}
//...
_addStock = async symbol => {
const { metas, quotes, charts, stocks } = this.state;
// check if stock already exists
const hasStock = stocks.filter(s => s.symbol === symbol).length;
if (hasStock) {
return;
}
const meta = await this._fetchMeta(symbol);
const quote = await this._fetchQuote(symbol);
const chart = await this._fetchChart(symbol);
const stock = {
symbol: symbol.toUpperCase(),
color: setStockColor(),
display: true
};
this.setState({
...this.state,
metas: [...metas, meta],
quotes: [...quotes, quote],
charts: [...charts, chart],
stocks: [...stocks, stock]
});
};
//...
componentDidMount() {
const initStocks = ["FB", "MSFT", "NVDA", "AAPL"];
initStocks.forEach(s => this._addStock(s));
}
答案 0 :(得分:1)
使用Promise.all并行获取多个网址。在你的情况下,粗略的工具将是:
SELECT
"QUERYID",
(SUM(UPVOTE)+ SUM(DOWNVOTE)) as "TOTAL"
FROM
"MY_TABLE"
WHERE
"QUERYID" in (15, 7)
GROUP BY
"QUERYID";
答案 1 :(得分:0)
多次调用_addStock
,多次调用setState
。这会导致多个setState
操作并行运行,而无需等待先前setState更新的确认。作为setState
异步操作,您会遇到如此奇怪的行为。
要解决此问题,您可以使用async/await
promise
级别
_addStock = async symbol => {
return new Promise((resolve,reject)){
this.setState({
...this.state,
metas: [...metas, meta],
quotes: [...quotes, quote],
charts: [...charts, chart],
stocks: [...stocks, stock]
},()=>{
resolve(true); //give confirmation setState is updates successfully.
});
}
};
使用_addStock
致电await
。
componentDidMount() {
const initStocks = ["FB", "MSFT", "NVDA", "AAPL"];
initStocks.forEach( async s => {
await this._addStock(s)
});
}
答案 2 :(得分:0)
当您在短时间间隔内多次调用setState
时,所有setState
调用批处理并集体执行它们,这就是为什么何时调用setState
第二次第一次请求仍处于待处理状态时组件state
在结尾处为空,只插入一个项目。
您可以使用以下方法异步传输数据,并且只使用最终数据更新状态一次。因为它没有为每次迭代使用状态,所以它也将保持数据一致性。
_addStock = symbols => {
const { metas, quotes, charts, stocks } = this.state;
// a variable to keep track how many symbols have been processed
let count = 0;
symbols.forEach(async symbol => {
// check if stock already exists
const hasStock = stocks.some(s => s.symbol === symbol);
if (!hasStock) {
//make all api requests in parallel
let meta = this._fetchMeta(symbol);
let quote = this._fetchQuote(symbol);
let chart = this._fetchChart(symbol);
let stock = {
symbol: symbol.toUpperCase(),
color: setStockColor(),
display: true
};
//wait for responses
meta = await meta;
quote = await quote;
chart = await chart;
//add all values to old state
metas.push(meta);
quotes.push(quote);
chart.push(chart);
stock.push(stock);
}
//update count
++count;
//if all values have been retrieved update state
if(count === symbols.length){
this.setState({
...this.state,
metas: [...metas],
quotes: [...quotes],
charts: [...charts],
stocks: [...stocks]
});
}
});
};
componentDidMount() {
const initStocks = ["FB", "MSFT", "NVDA", "AAPL"];
//Pass whole array to _addStock
this._addStock(initStocks);
}