用 Promise 如何把多个连续的异步过程写得优雅一点?

2016-05-18 17:17:35 +08:00
 SilentDepth

比如说做一件事分几个动作: step1 、 step2 、 finish ,前两个是异步的, step1 完成后才能执行 step2 (然后 finish )。我想到用 Promise 这么写:

let prom = new Promise((resolve, reject) => {
  // step1 ,用 setTimeout 模拟一下异步
  setTimeout(() => resolve('1'), 1000);
  // 先忽略 reject 相关动作
});
prom.then(data => {
  // step2
  setTimeout(() => {
    prom.then(data => {
      // finish
      console.log(`完成: ${data}`)
    });
  }, 1000);
});

可这样不就成 callback hell 了吗?而且从 step2 往后传数据也不方便。

由此引发的还有 step1 出错执行reject()如何中止整个过程的问题。

还是我对 Promise 的理解有问题?

14188 次点击
所在节点    JavaScript
36 条回复
leojoy710
2016-05-19 08:16:50 +08:00
@SilentDepth 原来是我说的太简略...请看 @mcfog 的回复...
hging
2016-05-19 08:51:12 +08:00
async 大法好
SilentDepth
2016-05-19 09:41:48 +08:00
感谢 @napsterwu @xjp @mcfog
我发现我的问题在于不知道`then()`的参数返回一个 Promise 会并入外部的 Promise composition ( MDN 没有写啊……),看来还是我对 Promise 的理解不到位。

现在的问题就是中间的`catch()`如何优雅地中止掉整个 composition 。调用`reject()`后会直接跳到后面最近的 rejection handler ,然后就继续走正常路线了。不是应该有个`Promise.prototype.cancel()`之类的方法吗?

to @xjp : 另外,我说的是 ES2015 里的 Promise ,构造函数的参数必须要有,这个怪我一开始没说清。
napsterwu
2016-05-19 09:43:19 +08:00
@SilentDepth Promise.all()
hantsy
2016-05-19 10:13:18 +08:00
用 RxJS 代替。
SilentDepth
2016-05-19 13:48:45 +08:00
@napsterwu `Promise.all()`就不是分步了呀
napsterwu
2016-05-19 13:57:32 +08:00
@SilentDepth 我上面不是还发了个链接演示怎么分步么
napsterwu
2016-05-19 13:58:15 +08:00
napsterwu
2016-05-19 13:58:58 +08:00
@SilentDepth 抱歉没搞好,左上角要选择 ES6
SilentDepth
2016-05-19 17:39:12 +08:00
@napsterwu 我是说「 step2 的异步成功后执行 finish 」这个需求用`Promise.all()`不能实现
SilentDepth
2016-05-19 17:55:23 +08:00
通过空 Promise 实现了一个中止过程功能:
https://gist.github.com/SilentDepth/67866e565946e84b1409d16d294b6181
但感觉这样不优雅。

Any idea?
yolio2003
2016-05-19 19:47:16 +08:00
各种大神回复了,楼主还是没明白。。。
yolio2003
2016-05-19 22:53:59 +08:00
所以我觉得其实是 promise 本身的问题 (逃
jimliang
2016-05-20 00:08:16 +08:00
楼主对 Promise 根本不熟练,其次 step1 和 step2 的逻辑就是一样的,可以封装在一起。两行搞定
```
const step = data=>new Promise(resolve=>setTimeout(resolve, 1000, data));
step('1').then(step).then(data=> console.log(`完成: ${data}`));
```
SilentDepth
2016-05-20 09:09:02 +08:00
@jimliang 刚学。如果是需要各个动作可以独立工作呢?
jimliang
2016-05-20 09:35:30 +08:00
@SilentDepth 如果是独立的就另外处理。 Promise 的重点是形成 Promise 链, then 的函数要返回具体的对象或者 Promise 作为下一个传递。我看你把一个 Promise then 了两次,也就是说 resolve 后两个 then 都会执行并不会顺着一条链执行了。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/279595

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX