2015-04-10 12 views
1

Давайте предположим, что у меня есть следующий код:Как избежать этого шаблона «возможного обратного вызова»?

var foo = function(arg, continuation, behavior) { 
    if (arg > 1) { 
    // Do some work with arg, for example send a paged API request. 
    console.log("foo: " + arg--); 

    continuation(arg, continuation, behavior); 
    } else { 
    behavior(arg); 
    } 
}, 

bar = function(arg, continuation, behavior) { 
    if (arg > 2) { 
    // Do some other work with arg. 
    console.log("bar: " + arg--); 

    bar(arg, continuation, behavior); 
    } else { 
    continuation(arg, continuation, behavior); 
    } 
}; 

bar(3, foo, console.log); 

Идея заключается в том, что я хочу, чтобы указать в вызове bar, какая функция в конечном итоге будет обратного вызова foo, который будет называться спустя некоторое время в граф вызовов.

Например, я не мог бы хотеть, чтобы console.log окончательного значения arg, но и использовать его как число раз повторяются некоторое сообщение:

var baz = function(arg) { 
    for (var i = 0; i < arg; i++) { 
    console.log("baz"); 
    } 
}; 

bar(4, foo, baz); 

В данном случае я говорю, что я инъекционный поведение baz вместо поведения console.log.

В some code I wrote Я использую этот шаблон, чтобы ввести поведение, которое я хочу. Например, cli.js вводит поведение печати некоторых записей на консоль, в то время как другой файл db.js (еще не написанный) может вводить поведение добавления этих записей в базу данных и т. Д.

Я не уверен, что это лучший способ добиться того, чего я хочу. Есть ли лучший способ сделать это?

+1

Я не понимаю, о чем вы просите. Ваши функции не возвращают никаких значений. Следовательно, я предполагаю, что вы используете их только для побочных эффектов. Функция 'foo' вообще не использует аргумент' продолжения'. Рекурсия в ваших функциях может быть преобразована в итерационные циклы. Еще лучше, просто установите 'if (arg> 2) arg = 2' в' bar' и 'if (arg> 1) arg = 1' в' foo'. Вам вообще не нужны петли. Я понятия не имею, что вы подразумеваете под инъекционным поведением. Все сказанное, вам нужно четко указать вашу проблему. Возможно, это проблема [xy] (http://ow.ly/LqxUq). –

+0

Мм, возможно, мое сокращение было недостаточно ясным. Я использую 'arg -' в качестве замены для выполнения некоторой работы с 'arg'. Например, подумайте о отправке запрошенного запроса API с помощью '{page: arg}'. –

+0

@AaditMShah Я отредактировал. Возможно, это имеет смысл? –

ответ

1

Вы намекнуть, что вы будете делать некоторые асинхронные задачи, поэтому давайте макет асинхронной задаче:

function mockApiRequest(mockResponse, callback) { 
    setTimeout(function() { callback(mockResponse) }, 500); 
} 

Теперь давайте изменят код немного, чтобы использовать наш запрос API:

function sendPages(pageNumber, continuation, behavior) { 
    if (pageNumber > 1) { 
    behavior('Uploading ' + pageNumber); 
    mockApiRequest({success:true}, function(apiResponse) { 
     if (apiResponse.success) { 
     behavior('Successfully uploaded ' + pageNumber); 
     continuation(pageNumber-1, continuation, behavior); 
     } 
     else { 
     behavior('Failed to upload ' + pageNumber); 
     } 
    }); 
    } else { 
    behavior('Unsure what to do with ' + pageNumber); 
    } 
} 

As правильно сформулированный Aadit, не очень хорошо для вашей функции изменять значение, переданное в него. Это «побочный эффект» функции и очень сильно отлаживает отладку, если вы не можете ожидать, что значение будет одинаковым во время исполнения. Таким образом, вы должны создать новое значение для следующего вызова продолжения. Вместо того, чтобы изменять arg на месте и проезжать arg, вы должны рассмотреть arg как неизменяемый.

Смежные вопросы