Promise 里要用到上一个执行过程里的变量怎么办?

2015-06-14 23:02:43 +08:00
 oott123

比如,

Q "Hello world"
.then (str)->
    "hello 2"
.then (str2)->
    # str 怎么获取?

备选方案 1:闭包法

Q "hello world"
.then (str)->
    Q "hello 2"
    .then (str2)->
        console.log str, str2

缺点:不好看,陷入了 callback hell。

备选方案 2:外部变量法

str = null
Q "hello world"
.then (s)->
    s = str
    "hello 2"
.then (str2)->
    console.log str, str2

缺点:用跨越作用域的变量,显得不太干净

备选方案 3:返回数组法

Q "hello world"
.then (str)->
    [str, "hello 2"]
.then (s)->
    console.log s[0], s[1]

缺点:返回值意义不明朗;要向下传递多层的时候麻烦。

所以大家遇到这种问题的时候怎么办?

3546 次点击
所在节点    JavaScript
12 条回复
br00k
2015-06-14 23:11:00 +08:00
我自己用的第一种。。
xream
2015-06-14 23:19:17 +08:00
我知道用 bluebird 可以 bind 到 this 上

.bind() also has a useful side purpose - promise handlers don't need to share a function to use shared state:

somethingAsync().bind({})
.spread(function (aValue, bValue) {
this.aValue = aValue;
this.bValue = bValue;
return somethingElseAsync(aValue, bValue);
})
.then(function (cValue) {
return this.aValue + this.bValue + cValue;
});
lilydjwg
2015-06-14 23:22:00 +08:00
理论上方案三最好。如果数组意义不明确,那么就用 object。实践上方案一写起来方便,但是变量太多的话效果与全局变量类似。
fundon
2015-06-14 23:26:36 +08:00
`spread` 返回多个值,是最方便的
joyee
2015-06-14 23:54:12 +08:00
用方案三,但用object。如果能用 ES6,配合 ES6 的 object literal shorthand

Promise.resolve("hello world")
.then(str => ({str1: str, str2: "hello 2"}))
.then(({str1, str2}) => console.log(str1, str2))
iwege
2015-06-15 00:01:00 +08:00
@fundon 这个是最好的办法。
MForever78
2015-06-15 00:13:15 +08:00
首先比较推荐使用 bluebird,API 比较丰富,性能也比较高,比 io.js 原生实现的都快。

如果几个执行过程是相互独立的,只是最终的返回的结果需要用到所有过程的结果,那就用 .spread

Promise.delay(500).then(function() {
return [fs.readFileAsync("file1.txt"),
fs.readFileAsync("file2.txt")] ;
}).spread(function(file1text, file2text) {
if (file1text !== file2text) {
console.log("files are equal");
}
else {
console.log("files are not equal");
}
});

如果后面的过程依赖前面过程的结果,就用第三种,传递的时候用 Object。
Axurez
2015-06-15 12:38:52 +08:00
这是啥语言?
orzfly
2015-06-15 13:06:54 +08:00
@Axurez CoffeeScript
oott123
2015-06-15 13:11:57 +08:00
@xream @MForever78 @fundon 谢谢你们,我觉得我心目中最好的方法大概就是 `spread` 这个 api。
至于 bluebrid 和 Q 嘛……一开始接触到的就是 Q 就一直用了,不过我倒是觉得 Q 的 api 比 bluebird 的好用一些……

@joyee coffee 里没有这么好用的语法…… coffee 作者似乎对 ES6 比较抵触。

@Axurez 是 coffeescript。
oott123
2015-06-15 13:13:16 +08:00
@br00k
@lilydjwg 第一种太难看了啊……
本来用 promise 就是为了避免这种一大堆的嵌套回调……
otakustay
2015-06-15 14:10:25 +08:00
我会选第三种,这种情况下数组其实是一个Tuple,从这个角度理解就是一个非常正常的数据结构了
其实更多的我会在第三种的基础上返回对象

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

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

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

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

© 2021 V2EX