Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在React中兑现承诺_Javascript_Reactjs_Promise - Fatal编程技术网

Javascript 在React中兑现承诺

Javascript 在React中兑现承诺,javascript,reactjs,promise,Javascript,Reactjs,Promise,寻找这个问题总会带来一些本质上可以归结为 class Test extends Component { componentDidMount() { this.props.promise.then(value => this.setState({value})); } render() { return <div>{this.state.value || "Loading"}</div>; } } 类测试扩展组件{ component

寻找这个问题总会带来一些本质上可以归结为

class Test extends Component {
  componentDidMount() {
    this.props.promise.then(value => this.setState({value}));
  }
  render() {
    return <div>{this.state.value || "Loading"}</div>;
  }
}
类测试扩展组件{
componentDidMount(){
然后(value=>this.setState({value}));
}
render(){
返回{this.state.value | |“Loading”};
}
}
如果(1)组件不会很快卸载,并且(2)承诺永远不会更改,则此操作有效。在试图提出更普遍的解决方案时,这两者都会产生潜在的问题

第一个问题可以通过添加“警卫”属性来解决,这不是什么大问题

当试图解决第二个问题时,很容易遇到竞争条件。考虑下面的代码:

const timedPromise=(值,延迟)=>新承诺((解析,拒绝)=>{
setTimeout(()=>解析(值),延迟);
});
类测试扩展了React.Component{
建造师(道具){
超级(道具);
this.state={value:“加载…”};
}
组件willmount(){
this.setPromise(timedPromise(“Hello 1”,3000));
设置超时(()=>{
this.setPromise(timedPromise(“Hello 2”,1000));
}, 1000);
}
承诺{
然后(value=>this.setState({value}));
}
render(){
返回{this.state.value};
}
}
render(,document.getElementById(“根”))

您可以通过跟踪指针来解决此问题,并且仅当解析的指针与当前指针(然后是最新的指针)匹配时才保存状态。否则就不管结果如何

设置后,这并不是保持状态为React的最佳方法。毕竟这是一个视图库。可能是Redux可以帮助您(或者可能太多,这也是可能的,真正取决于用例)

如果你想把一切都控制住,你可以这样做

class Example extends Component {
  constructor(props) {
    super(props);
    this.state({value: 'Loading', currentPointer: 0});
  }

  componentDidMount() {
    this.setPromise(timedPromise("Hello 1", 3000));
    setTimeout(() => {
      this.setPromise(timedPromise("Hello 2", 1000));
    }, 1000);
  }

  setPromise(promise) {
    const newPointer = this.state.currentPointer + 1;
    this.setState({currentPointer: newPointer}, () => 
      promise.then(value => {
        if (this.state.currentPointer == newPointer) {
          this.setState({value});
        } else {
          console.log(`Pointer mismatch, got ${newPointer} but current was ${this.state.currentPointer}`);
        }
      })
    });
  }

  render() {
    return <div>{this.state.data.value}</div>;
  }
}
类示例扩展组件{
建造师(道具){
超级(道具);
状态({value:'load',currentPointer:0});
}
componentDidMount(){
this.setPromise(timedPromise(“Hello 1”,3000));
设置超时(()=>{
this.setPromise(timedPromise(“Hello 2”,1000));
}, 1000);
}
承诺{
const newPointer=this.state.currentPointer+1;
this.setState({currentPointer:newPointer},()=>
承诺。然后(值=>{
if(this.state.currentPointer==newPointer){
this.setState({value});
}否则{
log(`指针不匹配,得到${newPointer},但当前为${this.state.currentPointer}`);
}
})
});
}
render(){
返回{this.state.data.value};
}
}

我知道你不想听这些,但react只是一个视图,你需要一些东西来管理你的状态。虽然您可能能够做到这一点,但从长远来看,使用Mobx或Redux会更好。请问这里的用例是什么?从未在同一生命周期方法中多次调用同一API方法。@Sag1v实际用例是多次调用
组件WillReceiveProps
。也就是说,如果组件是一个需要加载的工具提示,并且用户一直悬停在不同的项目上,那么当光标位于项目2上时,他可能会看到项目1的工具提示。我考虑过这一点,但它也会遇到竞争条件。如果在调用
setState({currentPointer:newPointer})
之前承诺已解决,该怎么办?正如我在问题中提到的,规范不保证
setState
的解析顺序。我已经编辑了示例,使用
this.setState()
的回调,因此您可以确定在进入承诺链之前,状态实际上已被修改。更多信息在啊,这更有意义,我忘记了
setState
可以同时使用修饰符和回调(我想你可能会存储实际的承诺而不是计数器)。如果你使用它作为比较,存储承诺也很好。两者都可以工作(尽管我喜欢消除指针值的想法,这基本上是元信息)。setState的回调对于只有3个承诺(例如)的项目非常有用,因此使用全部Redux有点过火;)(请随意编辑我的答案,顺便说一句)为什么首先要将
currentPointer
存储在
状态中?除了一个函数外,它与任何事物都完全无关。特别是它与状态更改触发的渲染周期无关。将其存储在
此中如何?\u currentPointer