2010-08-20 3 views
2

Этот вопрос заключается в том, чтобы выяснить, как передавать переменные между функциями javascript без: возвращать переменные, передавать параметры между первичными функциями, используя глобальные переменные и принудительную функцию 1 дождаться завершения функции 2. Я вычислил решение jQuery и разместил его ниже (в разделе ответов).Как получить переменную, возвращаемую через несколько функций - Javascript/jQuery


Old Post: Я инициализирую набор из четырех функций, каждый из которых вызывает друг друга по-другому. В конце этого мне нужен окончательный модифицированный продукт (массив), возвращаемый функции инициализации.

Глобальные переменные не заставляют начальную функцию ждать. И возврат его назад четыре раза тоже не работает. Как передать измененную переменную обратно в ее функцию инициализации, если вы не можете ее вернуть? Или почему он не возвращается?

(лабиринт начинается initFunctionA, заканчивается в functionD)

classOne = { 
    initFunctionA : function() { 
    classTwo.functionB(functionD, array); 
    // I NEED ACCESS TO ARRAY2 HERE 
    }, 
    functionD : function(data, array) { 
    var array2 = // modifications to array 
    } 
} 

{...} 

classTwo = { 
    functionB : function(callback, array) { 
    $.ajax({ 
     success: function(ret){ 
     classTwo.functionC(ret, callback, array) 
     } 
    }); 
    }, 
    functionC : function(ret, callback, array) { 
    callback(ret.data.x, array); 
    } 
} 
+0

Javascript массивы передаются по ссылке, так что если вы держите проходя тот же массив вложенных функций, которые вы должны получить измененный массив в последнем вызове. Не могли бы вы опубликовать полный рабочий код? –

+0

Этот код действительно не имеет никакого смысла; 'classTwo.function (functionB, array)' в частности. Вы говорите, что вы собираетесь * вызывать * функцию B там? – Pointy

+0

@axel_c - вы правы. Прости. Я создаю еще один массив (array2) в моей последней функции, используя первый массив. Я попытался просто сказать array = array2 в конце всего этого, но он все еще не работает. Он возвращает данные перед изменениями (initFunctionA работает без ожидания). Код действительно длинный. Я сделал исправления выше, хотя, надеюсь, это более понятно. Спасибо за вашу помощь! – Kyle

ответ

1

Изменить свой обратный вызов (в месте вызова), так что вы захватить возвращаемое значение functionD , Затем измените functionD так, чтобы он возвращался array2. Я добавил this доступ к приведенному ниже примеру в качестве удобства. (Кроме того, не забудьте включить точку с запятой, где «необходимая», если вы хотите сделать JSLint счастливым.)

classOne = { 
    initFunctionA : function() { 
    var self = this; 

    classTwo.functionB(function() { 
     var array2 = functionD.apply(self, arguments); 

     // ACCESS ARRAY2 HERE 
    }, array); 
    }, 
    functionD : function(data, array) { 
    var array2 = // modifications to array 

    return array2; 
    } 
}; 

{...} 

classTwo = { 
    functionB : function(callback, array) { 
    $.ajax({ 
     success: function(ret){ 
     classTwo.functionC(ret, callback, array) 
     } 
    }); 
    }, 
    functionC : function(ret, callback, array) { 
    callback(ret.data.x, array); 
    } 
}; 
+0

Я попытался реализовать это решение для письма, но я не получаю никаких данных. Хотя я тоже не ошибаюсь, что причудливо. Я бы заглянул в нее дальше, но я уже нашел решение, которое работает (тот, который я опубликовал). Сказав это, вы, кажется, знаете, о чем говорите. Я любитель, и я не хочу испортить переполнение стека МО, поэтому просто дайте мне «да, я уверен», и я приму это в качестве ответа. Проверьте свое опровержение и на свой комментарий, если у вас есть время. Благодаря! – Kyle

+0

@Emile, Можете ли вы опубликовать весь свой код? Вы уверены, что возвращаете 'array2' в' functionD'? Вы уверены, что пишете свой код, который обращается к 'array2' в анонимной функции в' initFunctionA', а не за пределами этой анонимной функции? – strager

+0

Я попробовал, а затем отменил свои изменения. Простите меня за то, что вы не отправляли код (я нахожусь в крайнем сроке и должен идти с моим взломанным решением). НО ... Я многое узнал из вашего подхода. Я передал массив2 вместе с несколькими другими параметрами, и я, возможно, не понял нюансов, идущих не только с одним. Это сказано, +1 и проверьте. Я думаю, это поможет кому-то точно. – Kyle

1

Вы не можете заставить его работать с рисунком, как вы там написано; это просто невозможно в Javascript, потому что нет такой вещи, как «ожидание». Ваш код ajax должен принимать параметр обратного вызова (который у вас есть, хотя неясно, откуда он или что он делает), и эта начальная функция должна проходить в коде, чтобы делать то, что вам нужно, с массивом после вызова ajax отделки.

+0

Я думаю, что я понял способ подражать «ожиданию» в javascript независимо от вызова ajax. Это работало для меня, но я был бы признателен за ваше мнение. Я ответила в этом разделе ответа. – Kyle

1

Я хотел бы использовать конструктор объекта:

function ClassOne() { 
    this.array2 = []; 
} 

ClassOne.prototype.initFunctionA = function() { 
    // ... 
} 

ClassOne.prototype.functionD = function(data, array) { 
    // Can use array2 EX: this.array2 
} 

var classOne = new ClassOne(); 
+0

Я считаю, что суть проблемы - асинхронный вызов ajax в середине вещей; это не имеет никакого отношения к тому, как создаются классы (хотя, как я понимаю, это трудно сказать). – Pointy

+0

@ Понятно, я понимаю, почему вы были в замешательстве. Я скрестил свой алфавит :) Я исправил буквы. @ChaosPandion ... Я вернусь к этому завтра и попробую ваше решение. – Kyle

+0

+1 Мне никогда не приходилось проверять это, потому что мне нужно было сохранять классы статичными и организованными, как и остальная часть проекта. Это может сработать, или может возникнуть проблема, которую вызвал Уокей. Я недостаточно осведомлен об этом. Я решил свою проблему по-другому (что я разместил ниже) ... но +1, потому что это может быть вполне допустимым решением, и похоже, что он может делать именно то, что вы говорите. – Kyle

0

Это, как я понимаю вашу проблему: classTwo обрабатывает вызов AJAX и может изменить результат. classOne использует classTwo для получения некоторых данных и нуждается в результирующих данных.

Если да, то как это:

classOne = { 
    initFunctionA : function() { 
    var array = ['a','b','c']; 
    classTwo.functionB(this.functionD, array); 
    }, 
    functionD : function(data, array) { 
    // This function is called when the AJAX returns. 
    var array2 = // modifications to array 
    } 
} 

{...} 

classTwo = { 
    functionB : function(callback, array) { 
    $.ajax({ 
     success: function(ret){ 
     classTwo.functionC(ret, callback, array) 
     } 
    }); 
    }, 
    functionC : function(ret, callback, array) { 
    callback(ret.data.x, array); 
    } 
} 

Так classOne.initFunctionA называет classTwo.functionB который устанавливает вызов Ajax. Когда вызов ajax завершается успешно, классTwo.functionC вызывается с результатом и исходным массивом. Отсюда, classOne.functionD вызывается с ret.data.x и массивом.

+0

Отличное понимание функции! Я не уверен, что вижу решение. Мне нужно использовать array2 в конце initFunctionA – Kyle

+0

Вы не сможете это сделать. Решение состоит в том, чтобы переместить весь код из initFunctionA, который полагается на array2 в functionD. Он будет вести себя так же, как функция была разделена на две части с задержкой в ​​середине (вызванной ajax). – Matt

+0

Правда, что @Matt. Хотя я только нашел решение, которое это делает. Опубликовано ниже. – Kyle

0

Хорошо! Я нашел способ передать переменные между функциями без:

  • делает глобальные переменные
  • делает свойство объекта (раствор Хаоса)
  • передачи параметров

Эти три были предложено здесь в качестве единственных путей ,

Accessing variables from other functions without using global variables

Но, если вы не можете передать параметры непосредственно, и вам нужно одну функцию ждать другой (то есть, не может полагаться на ссылки), и вы используете асинхронные вызовы в сервер в промежуточной функции, тогда ваше единственное решение:

Использование jQuery ...

Создайте этот объект в DOM (динамически, если вы не хотите, чтобы мутить разметку):

<div id='#domJSHandler" style="display: none;"></div> 

Тогда в функции, которая должна ждать:

//Function & Class Set 2 
$('#domJSHandler').bind('proceedWithAction', function(event, param1, param2) { 
    // action set 2 
}); 

И в функции ждем по:

//Function & Class Set 1 
// action set 1 
$('#domJSHandler').triggerHandler('proceedWithAction', [param1, param2]); 

По существу, необходимо выполнить последние действия, которые необходимо выполнить в jQuery привязать настраиваемое событие к невидимому объекту DOM. Запустите это событие из JS с помощью триггера jQuery. Передайте свои параметры и вуаля!

Я уверен, что SO даст мне дерьмо для этого (и для самовлюбленного принятия моего собственного ответа), но я думаю, что это очень блестяще для uber-новичка, и это сработало для меня.

Итак: р Переполнение стека (Ю.К. Вы все спасли мою задницу много раз, и я люблю тебя все :)

+1

Работа с DOM связана с глобальным состоянием.Я думаю, что это то, что означало «создание глобальных переменных», а не только использование глобалов JavaScript (т. Е. Свойств на «окне» в браузере). – strager

+0

Ограничение глобальных переменных как решение для управления порядком функций (например, при использовании ajax) состоит в том, что вторая (3-я, 4-я) функция выполняет свои операции над переменной, а 1-я функция продолжается. Но я согласен с вами концептуально. Просто глобальные решения не решили мою асинхронную проблему. Это так. (хотя я только что видел ваше сообщение, позвольте мне проверить его) – Kyle

+0

и .unbind() перед .bind (...), если пользователь снова может вернуть эту страницу. – Kyle

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