2013-08-13 2 views
2

У меня в моем коде много проблем, потому что это не синхронно. Вот пример проблемы, которая у меня есть в расширении chrome. Это моя функцияJavascript синхронные функции - расширение хром

function getTranslation(a_data, callback) 
{   
    var apiKey = '####'  
    var json_object = {}; 
    var url = '###'; 
    var xmlhttp; 
    var json_parsed = {}; 

    storage.get('data', function(items) 
    { 
     json_object = { 
      'text': a_data, 
      'from' : items.data.from, 
      'to' : items.data.to 
     }; 
     var json_data = JSON.stringify(json_object); 

     if (window.XMLHttpRequest) 
     { 
      xmlhttp=new XMLHttpRequest(); 
     } 
     else 
     { 
      xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); 
     } 

     xmlhttp.open("POST", url, false); 
     xmlhttp.setRequestHeader("Content-type","application/json");   
     xmlhttp.setRequestHeader("Authorization","##apiKey=" + apiKey);      
     xmlhttp.setRequestHeader("X-Requested-With","XMLHttpRequest");      
     xmlhttp.send(json_data); 

     json_parsed = JSON.parse(xmlhttp.responseText); 
     callback(json_parsed.translation); 
    });      
} 

Это, как я использую функцию getTranslation в другой функции:

for (counter in toTranslateArray) 
{ 
    getTranslation(toTranslateArray[counter],function(callback) 
    { 
     translated += callback; 
     console.log(translated); //this is second and works 
    }); 
} 
console.log(translated); //this is first and empty 
//code depending on translated 

Является ли это что-то плохое?

+0

Задайте функцию json_data внутри функции обратного вызова. – apsillers

+0

Хорошо, но это всего лишь часть функции и не решила мою проблему. После этого у меня есть запрос ajax, который использует json_data. И я получу json_data undefined. – smotru

+0

Поместите любой код, который должен использовать 'json_data' внутри обратного вызова, или внутри функции, которая вызывается в обратном вызове и принимает' json_data' в качестве аргумента. Если вы поместите свой вызов Ajax внутри обратного вызова, он получит доступ к 'json_data'. – apsillers

ответ

0

Поскольку вы используете синхронизацию XHR, вместо ajax вам нужно использовать функцию синхронизации для сохранения данных вместо chrome.storage, которая является асинхронной.

В документации chrome.storage, одна из его особенностей является

  • Это асинхронный с насыпью операций чтения и записи, и, следовательно, быстрее, чем блокирование и серийный localStorage API.

Но быть блокирование (и синхронизация) является то, что вы хотите, так почему бы вам не изменить к этому API вместо этого?

Или еще лучше:

Преобразование getTranslation() функцию, чтобы быть асинхронной. Вам нужно будет добавить третий параметр, который будет обратным вызовом, и использовать его внутри вложенных обратных вызовов (потому что если вы это сделаете, вы также можете использовать ajax вместо синхронизации XHR).

Таким образом, это правильно, но если вы чувствуете, ленивы и хотят более простой способ, просто сделать первый и изменить chrome.storage к localStorage, и вы сделали.

EDIT: Я вижу, вы уже изменили свою функцию как асинхронный. И это, кажется, работает правильно, но вы обновили свой вопрос, и вы, кажется, есть проблемы хватательные, почему эта линия не работает:

console.log(translated); //this is first and empty 

Вы должны понимать, как событие ориентированного программирования работы. Вы можете думать, что линия

for (counter in toTranslateArray) 

который содержит getTranslation означает «сделать перевод каждого счетчика внутри этой toTranslateArray», но на самом деле означает «огонь событие перевода для каждого счетчика внутри этой toTranslateArray».

Это значит, что console.log выполняет следующие функции: только что снято; он не ждет, пока он будет завершен. Поэтому перевод в этот момент пуст. И это нормально, выполняется async.

Я не знаю, что вам нужно сделать с translated var раз завершено, но я попытался бы запустить другое событие после обработки последнего элемента массива.

Но в любом случае вам нужно изучить учебник или что-то в программировании, ориентированном на события, поэтому все это имеет для вас больше смысла.

Об localStorage, я не знаю, я узнал об этом в качестве альтернативы в документации chrome.storage, я действительно не знаю, как ее использовать в вашем случае.

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

0

Создайте пользовательский прослушиватель событий, где после того, как вы закончите с строкой json_data (сделанный внутри обратного вызова, как предлагается), он затем запустит событие для вызова ajax. Перейдите сюда, чтобы узнать больше о событии cusotm JavaScript custom Event Listener

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