在 javascript 中使用适当的回调作为延续

Using callbacks appropriate as continuations in javascript

我熟悉回调,我知道同步性是什么,但在继续传递样式方面我仍然缺少一些东西。我有这个简单的代码示例,我不知道如何根据连续传递样式的回调将其转换为异步代码:

function performOrder() {
  var available, placedOrder;
  available = checkCountOnServer(order.item, order.count);
  if (!available) {
    showNotAvailableMessage(order);
    return;
  }
  placedOrder = checkPayment(order.item, order.count, order.paymentMethod);
  if (askUserForConfirmationWithDialog(placedOrder)) {
    return confirmOrder(placedOrder);
  }
}

我对此的处理方法是:

function performOrder() {
  checkCountOnServerC(order.item, order.count, showNotAvailableMessage(order));
  return checkPaymentC(order.item, order.count, askUserConfirmationWithDialogC(placedOrder, confirmOrder(placedOrder));
}

可以假设所有附加了 C 的方法都被修改为接受回调作为继续。

我的问题是:这两个片段是否等同并确认第二个片段与继续传递样式相同?

非常感谢您!

无论 available 的状态如何,您的代码都将并行执行 checkCountOnServerCcheckPaymentC。因此它们不等价。

正确的转换取决于您要采用的样式:node.js 标准回调样式、Promises、successCallback/errorCallback 等。假设您要使用 node.js 标准回调样式:

function performOrderC(callback){
    checkCountOnServerC(order.item, order.count, function(err, available){
        if (! available ) {
            showNotAvailableMessage(order));
            callback(new Error('Not available'));
            return;
        } 
        checkPaymentC(order.item, order.count, function(err, placedOrder){
            askUserConfirmationWithDialogC(placedOrder, function(){
                callback(null, confirmOrder(placedOrder)); // this is how you "return" results
           });
       });
    });
}

Node.js 标准回调样式使用回调的第一个参数将错误向上传递到堆栈。但在 node.js 之前,这并没有被异步函数普遍采用。

如果上面的内容看起来有点密集(有时称为回调地狱),您可以随时重构它以不使用匿名函数:

function checkPaymentHandler (callback) {
    return function (err, placedOrder){
        askUserConfirmationWithDialogC(placedOrder, function(){
            callback(null, confirmOrder(placedOrder)); // this is how you "return" results
        });
    });
}

function checkCountHandler (callback) {
    return function (err, available) {
        if (! available ) {
            showNotAvailableMessage(order));
            callback(new Error('Not available'));
            return;
        } 
        checkPaymentC(order.item, order.count, checkPaymentHandler(callback));
    }
}

function performOrderC(callback){
    checkCountOnServerC(order.item, order.count, checkCountHandler(callback));
}