我有一个纯粹同步的验证库,但通常用作异步函数链的一部分.但是,我必须维护一个现有的同步API,并希望将promise API作为可选项.我可以以某种方式检测(在运行时)函数是否是Promise链的一部分?
回调这很容易,因为你可以检查是否传入了一个回调.我明白我可以传递一个可选的promise boolean,但这看起来不太优雅.
我还考虑过做一个回调接口,并使用库将回调接口转换为基于promise的接口.但是,我在Haxe工作,我宁愿将变换/抽象降到最低.
我也明白你可以将承诺之间的常规函数夹在中间,但是在某些情况下,两者之间的行为会有所不同.
最终编辑很多关于为什么我不能只返回相同值的混淆,第一个例子(下面)似乎没有帮助.请记住,这仍然是简化的.
//mix of sync with promise new Promise(function(resolve, reject){ var safeToAdd = thingTracker.preflight(newThing); if(safeToAdd){ return client.request.addThing(newThing); //send request to server } else { reject(newThing.errorMessages); //requires explicit reject, cannot just pass results along } }).then(function(newThing){ //client and server both cool with newThing? thingTracker.save(newThing); }).catch(function(errorMessages){ //handles errorMessages from client and server ui.show(errorMessages); }); //pure promise thingTracker.preflight(newThing).then(function(){ return client.request.addThing(newThing); //sends request to server }).then(function(newThing){ //client and server both cool with newThing? thingTracker.save(newThing); }).catch(function(errorMessages){ //handles errorMessages from client and server ui.show(errorMessages); });
(旧)编辑澄清(但并非真的):
function preflight(thing){ var validity = thing === 42; if(promise){ if(validity){ return Promise.resolve(validity); } else { return Promise.reject(validity); } } else { return validity; } }
显然我可以在then
anon函数中进行相同的检查,但这并不比直接使用同步接口好多少.另请注意,这是一个非常简单的示例,在实际功能中会产生副作用thing
并产生消息.
编辑只是为了更好地说明我的观点,这里有一些事情的主旨.
可以在promise链中使用同步函数.如果您有一个这样调用的同步API调用:
var info = myApi("foo");
这可以在承诺链中使用得很好:
someAsyncCall().then(myApi).then(someOtherFunction)
您不需要使myApi异步或返回以这种方式使用的承诺.在具有同步函数的promise链中,你唯一不能做的就是它不能是链中的第一个项,但它不需要.由于它是同步的,所以只要有人想要它首先执行,就可以在启动链之前调用它.或者,最坏的情况,您可以这样做:
Promise.resolve().then(myAPI).then(someOtherFunction);
我可以以某种方式检测(在运行时)函数是否是Promise链的一部分?
不,你不能(除非你明确地传递了一些告诉它的信息),你不需要为了在诺言链中使用它.您不需要将promise作为.then()
处理程序返回.您只需返回一个值,该值将成为链中该点的promise链的值.
我也明白你可以将承诺之间的常规函数夹在中间,但是在某些情况下,两者之间的行为会有所不同......例如返回false和抛出消息.
我不清楚为什么这种行为必须是不同的.如果返回false
是正常的同步行为,那么你可以在promise链中做到这一点 - 链中的下一步只需要处理false
传递给它的值,就像下一行同步代码那样.如果抛出异常是你的正常行为,你也可以在promise链中做到这一点(promise链会将异常变成拒绝),以下代码可以决定它想要处理的方式.如果您的同步函数根据它是否是promise链的一部分而表现不同,那么可以提出一个很好的论据.如果你看到两个不同行为的充分理由,那么你应该有两个不同的功能(可以用不同的方式记录)或传入的选项来确定行为.
根据您在编辑中添加的代码进行评论
您似乎认为通过承诺链调用时,您需要返回已解决或拒绝的承诺链.你不需要这样做.您只需返回一个正常值,promise链将继承您返回的值.除非你想让它成为promise链中的第一个函数,否则没有理由返回已解决或被拒绝的promise,但在这种情况下,它仍然不在promise链中,所以你永远无法检测到它.并且,没有理由将同步操作作为承诺链中的第一个操作.只需先调用同步操作,然后使用异步操作启动您的promise链.
这是一个在promise链中使用的同步函数的演示:
function log(str) {
var div = document.createElement("div");
div.innerHTML = str;
document.body.appendChild(div);
}
// test async call
function delay(t, val) {
return new Promise(function(resolve) {
setTimeout(function() {
resolve(val);
}, t);
});
}
function square(x) {
return x * x;
}
log("Calculating the square of 9");
delay(500, 9).then(square).then(function(result) {
log("Result = " + result);
});