2013-04-13 5 views
0

Я пытаюсь использовать функцию обратного вызова в первый раз, и у меня возникают проблемы с ее работой. Вот упрощенная версия моего кода:Почему не работает эта функция обратного вызова?

var unsavedChanges = 1; 

function saveData(callback) 
{ 
    // save data 

    if(typeof callback === "function") 
    { 
     unsavedChanges = 0; 
     callback.apply(arguments); 
    } 
} 

function nextStep(val) 
{ 
    if(unsavedChanges == 1) 
    { 
     saveData(nextStep, val); 
     return false; 
    } 

    console.log(val); 
} 

nextStep("test"); 

JSFiddle: http://jsfiddle.net/tXqn3/

Внутри моей реальной функции «сейв» Я сохраняю данные, используя $.ajax() и у меня есть обратный вызов в функции .done(). Таким образом, если на странице есть несохраненные данные, они сохраняются, а затем запускается исходная функция, которая была вызвана.

С помощью этого кода значение undefined распечатывается на консоль при запуске кода. Что я делаю не так?

+1

'callback.apply (аргументы)'? Вы применяете обратный вызов для обратного вызова? – elclanrs

+0

@elclanrs Я читал, что это вызывает функцию обратного вызова с аргументами. То есть это то же самое, что делать callback (arguments [1], ...); ', но с тем преимуществом, что аргументы не должны быть жестко закодированы. – Nate

+0

Можете ли вы разместить «настоящий» код. Трудно определить, что такое 'arguments', если это набор, включающий' callback', или если это аргументы 'done' (поскольку вы упомянули, что они завернуты в' done'). – Joseph

ответ

6

У вашего кода две проблемы.

Во-первых, обратите внимание на определение apply: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/apply

Вы пропустили первый аргумент thisArg, который является то, что следует использовать в качестве this внутри функции вы претендуете.

Во-вторых, я не думаю, что вы действительно хотите передать arguments в заявку. То, что вы хотите, - это почти первый аргумент, поскольку первый аргумент - callback. Поэтому вы можете использовать Array.prototype.slice.call(arguments).slice(1), чтобы получить все аргументы, кроме первого, и передать это в apply.

Вот рабочая скрипку с этими изменениями: http://jsfiddle.net/UkdT7/1/

+0

Ударьте мне, и твердые объяснения. +1 –

1

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

var unsavedChanges = 1; 

function saveData(callback) 
{ 
    // save data 

    if(typeof callback === "function") 
    { 
     unsavedChanges = 0; 
     callback(); // no callback.apply 
    } 
} 

function nextStep(val) 
{ 
    if(unsavedChanges == 1) 
    { 
     saveData(function() { 
      nextStep(val); 
     }); 
     return false; 
    } 

    console.log(val); 
} 

nextStep("test"); 

http://jsfiddle.net/mattball/YxDkg

+0

Очень элегантный, спасибо! – Nate

1

применяются функции получает thisArg как первый arugment, а затем массив в качестве второго аргумента, так что вам нужно сделать это

callback.apply(this,arguments); 

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/apply

+1

Однако это не полное исправление, поскольку оно не будет записывать '' test''. –