我有很多异步方法要执行,我的程序流程可能会根据每个方法的返回值发生很大变化。下面的逻辑是一个例子。我无法使用 Promises 以易于阅读的方式编写它。你会怎么写?
Ps:欢迎更复杂的流程。
Ps2:is_business 是一个预定义标志,我们在其中说明我们是在写“企业用户”还是“个人用户”。
begin transaction
update users
if updated
if is_business
update_business
if not updated
insert business
end if
else
delete business
end if
else
if upsert
insert user
if is_business
insert business
end if
end if
end if
commit transaction
最佳答案
promises 的好处在于它们在同步代码和异步代码之间做了一个简单的类比。举例说明(使用 Q 库):
同步:
var thisReturnsAValue = function() {
var result = mySynchronousFunction();
if(result) {
return getOneValue();
} else {
return getAnotherValue();
}
};
try {
var value = thisReturnsAValue();
console.log(value);
} catch(err) {
console.error(err);
}
异步:
var Q = require('q');
var thisReturnsAPromiseForAValue = function() {
return Q.Promise(function() {
return myAsynchronousFunction().then(function(result) {
if(result) {
// Even getOneValue() would work here, because a non-promise
// value is automatically cast to a pre-resolved promise
return getOneValueAsynchronously();
} else {
return getAnotherValueAsynchronously();
}
});
});
};
thisReturnsAPromiseForAValue().then(function(value) {
console.log(value);
}, function(err) {
console.error(err);
});
您只需要习惯这样的想法,即返回值始终作为 then-callbacks 的参数访问,并且链接 promise 等同于组合函数调用 (f(g(h(x)))
) 或以其他方式按顺序执行函数 (var x2 = h(x); var x3 = g(x2);
)。基本上就是这样!当您引入分支时,事情会变得有点棘手,但您可以从这些基本原则中找出要做什么。因为 then-callbacks 接受 promises 作为返回值,所以您可以通过为异步操作返回另一个 promise 来改变您异步获得的值,该异步操作解析为基于旧值的新值,并且父 promise 将在新的解决之前不解决!当然,您可以从 if-else 分支中返回这些 promise 。
上面示例中说明的另一个非常好的事情是 promise (至少是符合 Promises/A+ 的 promise )以同样类似的方式处理异常。 “引发”的第一个错误绕过非错误回调并冒泡到第一个可用的错误回调,很像 try-catch block 。
就其值(value)而言,我认为尝试使用手工制作的 Node.js 风格的回调和 async
库来模仿这种行为是一种特殊的 hell :)。
遵循这些准则,您的代码将变成(假设所有函数都是异步的并返回 promise ):
beginTransaction().then(function() {
// beginTransaction() has run
return updateUsers(); // resolves the boolean value `updated`
}).then(function(updated) {
// updateUsers() has "returned" `updated`
if(updated) {
if(isBusiness) {
return updateBusiness().then(function(updated) {
if(!updated) {
return insertBusiness();
}
// It's okay if we don't return anything -- it will
// result in a promise which immediately resolves to
// `undefined`, which is a no-op, just like a missing
// else-branch
});
} else {
return deleteBusiness();
}
} else {
if(upsert) {
return insertUser().then(function() {
if(isBusiness) {
return insertBusiness();
}
});
}
}
}).then(function() {
return commitTransaction();
}).done(function() {
console.log('all done!');
}, function(err) {
console.error(err);
});
关于javascript - 避免 javascript 回调和 promise hell ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38862022/