
困扰了很久的异步问题 一般来说,想要 JS 程序顺序执行,会借助 Promise 的链式结构来顺序调用程序
new Promise(resolve => { Afunc(); resolve(any); }).then( res=>{ Bfunc(); }) 现在我想要做更复杂一点的事,例如 Afunc 里是 react 组件里的一个发请求并 setState 的函数
Afunc = () =>{ axios.post(`xxx`,{params}).then(res=>{ if(res.xxxx === 'xxxx'){ this.setState({},callBackFunc); } }) } 我有一些业务函数(操纵 UI,脏代码)要在 setState 之后才做,也就是塞在 callBackFunc 里 显然
new Promise(resolve=>{ Afunc(); resolve // resolve 之后不知道多少个 then 才执行 Afunc 里的 .then(res=>{...}) }) 不满足我新产生的想法。因为 resolve 的时候 Afunc 只跑到 post, .then 里的代码还没轮到 那么我的问题是,如何在不往 Afunc 里塞 callback 的实现一个可以操控的事件流 我现在的做法
Afunc = (callback) =>{ ... this.setState({},()=>{ callback && callback(); }) } 《 You don't know JS 》里看到的好像是 setTimeout 和 promise 混用的时候,把 resolve 给塞到 setTimeout 中的函数 promise((solve)=>{setTimeout(()=>{func, resolve},1000)}
P.S.(如果要手动实现事件队列那还是算了)
P.S. async/await generator 这些也基于 Promise 的语法糖,真的会有用吗?
1 AlphaTr Feb 27, 2020 via iPhone 把 Afunc 包装成 promise |
2 maichael Feb 27, 2020 大概能这么干,但我没有实测。 Afunc = async () => { const res = await axios.post(`xxx`, {params}) if(res.xxxx === 'xxxx') { retrun new Promise(resolve => this.setState({}, resolve)) } } 用的时候直接 await Afunc() otherFunc() 或者 Afunc().then() |
3 crysislinux Feb 27, 2020 2 楼的办法就可以了 |
4 kof21411 Feb 27, 2020 2 楼方法正确,async/await 异步变同步 |
6 aaronlam Feb 27, 2020 我现在在项目里基本上用 async await 就能解决很多异步顺序执行的问题 |
7 love Feb 27, 2020 async/await 直观多了,虽然可以做的事回调和 promise 都能做 |
8 TheCZ Feb 27, 2020 这个帖子需要 马克一下 最近遇到同样的疑惑! |
9 ethusdt Feb 27, 2020 @azcvcza #5 「我有一些业务函数(操纵 UI,脏代码)要在 setState 之后才做,也就是塞在 callBackFunc 里」显然就需要在 setState({}, callback) 塞回掉了,避免不了的。 所以你的问题答案是: return new Promise(r => this.setState({}, r)) |
10 mmdsun Feb 27, 2020 via Android async/await 可以看一下 msdn 异步文档。async/await 和 Rx 系列,最早都是微软搞出来模型。官方文档很全面。 然后对比学习 coroutine stackful。js 的 async/await 和 fibjs,还有 c#的 async/await,go 的 goroutine。这样异步就不会有什么问题了。 |
12 azcvcza OP @mmdsun 实际上 js 里的 async/await 是包了一层 promise 在里边,我其实真正想知道的是,除了 async/await,和 promise 这系列的顺序流操纵之外,除了往函数参数里塞回调,是不是还会有其他一些通用的,确定异步函数完成时机的东西。当然我自己翻 js 高程,you don‘t know js 没找到这么细的,you don't know 里提到最接近的就是 promise 里塞一个 setTimeout,在 setTimeout 里 resolve 了。生成器看是看了,但平常用的太少 |
14 duan602728596 Feb 28, 2020 class Com extends React.Component { state = { data: [] }; changeData(data) { return new Promise((resolve, reject) => { this.setState({ data }, resolve); }); } async getData() { const res = await fetch(url); const data = await res.data.json(); await this.changeData(data); // 之后要做的事情 } componentDidMount() { this.getData(); } } 根据你的意思写的模拟的代码,就这个意思? |
15 StrayBugs Feb 28, 2020 via Android 你想的方向不对 > 我有一些业务函数(操纵 UI,脏代码)要在 setState 之后才做 react 何时应用更新 states 是不可知的,那么这些副作用应该放到生命周期或者 effect hooks 中处理。 |
16 StrayBugs Feb 28, 2020 via Android 好吧,才发现 setState callback 也是安全的,这么用得比较少,补了个盲点。那么 2 楼是正解。 |
18 azcvcza OP @duan602728596 差不多是这样,你的拆分看起来合适,但本质上还是往里边塞回调了 |