这是我认为你应该做的方式。
链的分离
因为两个函数都将使用 amazingData,所以有一个专门的函数来处理它是有意义的。
每当我想要重复使用一些数据时,我通常会这样做,以便它始终作为函数参数存在。
由于您的示例正在运行一些代码,因此我假设所有内容都在一个函数中声明。我将其称为 toto()。
然后我们将有另一个函数,它将运行 afterSomething() 和 afterSomethingElse()。
function toto() {
return somethingAsync()
.then( tata );
}
你还会注意到,我添加了一个
return语句,因为这通常是Promise的常规用法-你总是返回一个promise,以便我们可以继续链接。在这里,
somethingAsync()将生成
amazingData,并且它将在新函数中的任何地方都可用。
现在,这个新函数的外观通常取决于
processAsync()是否也是异步的?
processAsync不是异步的
如果
processAsync()不是异步的,那么没有理由过度复杂化。一些旧的好的顺序代码就可以了。
function tata( amazingData ) {
var processed = afterSomething( amazingData );
return afterSomethingElse( amazingData, processed );
}
function afterSomething( amazingData ) {
return processAsync( amazingData );
}
function afterSomethingElse( amazingData, processedData ) {
}
请注意,无论
afterSomethingElse()是否执行异步操作都没有关系。如果是异步操作,则会返回一个Promise并继续链式调用。如果不是异步操作,则将返回结果值。但由于该函数是从
then()中调用的,因此该值将被包装成一个Promise(至少在原始JavaScript中)。
processAsync异步
如果
processAsync()是异步的,则代码将略有不同。在这里,我们假设
afterSomething()和
afterSomethingElse()不会在其他地方重复使用。
function tata( amazingData ) {
return afterSomething()
.then( afterSomethingElse );
function afterSomething( ) {
return processAsync( amazingData );
}
function afterSomethingElse( processedData ) {
}
}
afterSomethingElse()与之前相同。它可以是异步的,也可以不是。将返回一个promise,或将值包装为已解决的promise。
您的编码风格与我以前使用的非常接近,这就是为什么我即使过了两年还回答的原因。我不太喜欢在各处使用匿名函数,我发现它很难阅读,即使在社区中很常见。这就像我们用
promise-purgatory代替了
callback-hell一样。
我也喜欢在
then中保持函数名称简短。它们只会在本地定义。大多数情况下,它们将调用另一个已在其他地方定义的可重用函数来完成工作。甚至对于只有一个参数的函数,我也这样做,这样我就不需要在添加/删除函数签名中的参数时进出函数。
饮食示例
以下是一个示例:
function goingThroughTheEatingProcess(plenty, of, args, to, match, real, life) {
return iAmAsync()
.then(chew)
.then(swallow);
function chew(result) {
return carefullyChewThis(plenty, of, args, "water", "piece of tooth", result);
}
function swallow(wine) {
return nowIsTimeToSwallow(match, real, life, wine);
}
}
function iAmAsync() {
return Promise.resolve("mooooore");
}
function carefullyChewThis(plenty, of, args, and, some, more) {
return true;
}
function nowIsTimeToSwallow(match, real, life, bobool) {
}
不要过多关注
Promise.resolve(),它只是创建一个resolved promise的快捷方式。
我试图通过这种方式实现在单个位置运行所有的代码 - 就在
then下面。
其他具有更具描述性名称的函数都是可重用的。
这种技术的缺点是定义了许多函数。
但是,为避免匿名函数散落在各处,这是一种必要的痛苦。
反正又有什么风险呢:堆栈溢出吗?(开玩笑!)
使用其他答案中定义的数组或对象也可以。这个答案在某种程度上就是
Kevin Reid提出的答案。
你还可以使用
bind()或
Promise.all()。请注意,它们仍然需要你拆分代码。
使用bind
如果你想保持函数的可重用性,但实际上不需要将
then中的内容保持非常简短,你可以使用
bind()。
function tata( amazingData ) {
return afterSomething( amazingData )
.then( afterSomethingElse.bind(null, amazingData) );
}
function afterSomething( amazingData ) {
return processAsync( amazingData );
}
function afterSomethingElse( amazingData, processedData ) {
}
为了简单明了,当调用函数时,
bind()会将参数列表(除第一个参数外)作为首个参数添加到该函数中。
使用Promise.all
在您的帖子中,您提到了
spread()的使用。我从未使用过您正在使用的框架,但是以下是您应该能够使用它的方法。
有些人认为
Promise.all()是解决所有问题的方法,所以我想提一下。
function tata( amazingData ) {
return Promise.all( [ amazingData, afterSomething( amazingData ) ] )
.then( afterSomethingElse );
}
function afterSomething( amazingData ) {
return processAsync( amazingData );
}
function afterSomethingElse( args ) {
var amazingData = args[0];
var processedData = args[1];
}
你可以将数据传递给
Promise.all() - 注意数组的存在 - 只要承诺,但确保没有承诺失败,否则它将停止处理。
而且,您应该能够使用spread()代替then()从args参数定义新变量以进行各种令人惊叹的工作。