2016-05-12 3 views
0

Вот несколько кодов.Weird Ошибка закрытия Javascript

function callServiceSync(url, obj) { 
    var result = true; 
    callServiceOptions(url, obj, function(res){ 
     result = res; 
     alert("RESULT CB: "+JSON.stringify(result)); 
    }, {async: false}); 
    alert("RESULT POST-CB: "+JSON.stringify(result)); 
    return result; 
} 

Когда он работает, то окно предупреждения говорит:

РЕЗУЛЬТАТ CB: { "Успех": правда, "данные": "dtrombley"}

(это то, что WebService возвращается, в действительности), а затем:

РЕЗУЛЬТАТ POST-CB: истинные

Почему это назначение переменной закрытия не работает? Я не понимаю, как работает JS?

callServiceOptions() довольно длинный, но суть в том, что он вызывает метод $ .ajax jQuery с последними параметрами аргументов, расширенными до некоторого значения по умолчанию (в этом случае async отключается для запроса синхронизации), а затем выполняется предоставленный обратный вызов.

Возможно, что $ .ajax() может каким-то образом выполнить что-то, что отключает/запирает затворы (но I называет cb, а не $ .ajax()!)? Если да, то как это исправить?

Для полноты (хотя на самом деле эта функция не должна быть в состоянии ввернуть вещи по-моему):

function callServiceOptions(url, obj, cb, options) { 
    optSuccess = options.success; 
    optError = options.error; 
    opts = {} 
    $.extend({},options) 
    if (!opts.contentType) { 
     opts.contentType = "application/json"; 
    } 
    if (!opts.dataType) { 
     opts.dataType = "json"; 
    } 
    if (!opts.data && obj) { 
     opts.data = JSON.stringify(obj); 
    } 
    if (!opts.processData) { 
     opts.processData = false; 
    } 
    if (!opts.method) { 
     opts.method = "POST"; 
    } 
    opts.error = function(jqXHR, textStatus, errorThrown) { 
     if (optError) { 
      optError(jqXHR, textStatus, errorThrown); 
     } 
     if (jqXHR.responseText) { 
      responseObj = JSON.parse(jqXHR.responseText) 
      if (responseObj && responseObj.message) 
      cb({ 
       success: false, 
       message: responseObj.message 
      }) 
      return 
     } 
     cb({ 
      success: false, 
      message: errorThrown 
     }); 
    }; 
    opts.success = function(data, textStatus, jqXHR) { 
     if (optSuccess) { 
      optSuccess(data,textStatus,jqXHR); 
     } 
     cb(data); 
    }; 
    if (url.charAt(0) == '/') { 
     url = url.substr(1); 
    } 
    opts.url = WEBCTX.getBaseURL() + url; 

    $.ajax(opts); 
} 

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

+0

Quentin - Пожалуйста, внимательно прочитайте вопрос. Я не выполняю асинхронный вызов, я выполняю синхронный вызов, и значение возвращается правильно из jQuery ajax(). – BadZen

+1

Нет, есть синхронный режим запроса, и именно это я использую. Пожалуйста, прочитайте документацию по адресу http://api.jquery.com/jquery.ajax/ и особенно бит об опции «async», которую я использую. – BadZen

+0

Если это было асинхронно, предупреждения не вернутся в этом порядке, а наоборот. – BadZen

ответ

6

Ваша функция асинхронная.

Пока вы создали объект, который выглядит как {async: false}, вы передаете его как 4-й аргумент callServiceOptions, поэтому он помещается в переменную options.

Вы получаете доступ только эту переменную дважды (options.success и options.error), поэтому async свойство не используется ни для чего (так $.ajax использует значение по умолчанию true).

Добавление console.log(opts) как раз перед тем, как вы позвоните $.ajax(opts);, покажет это.

+0

Ах, моя ошибка. Я видел логику 'extend', я думал, что опции расширяются до выбора. – Quantastical

+2

@Quantastical, '$ .extend' изменяет первый аргумент и возвращает его, но вы не фиксируете возвращаемое значение. – trincot

+0

Ook. Я тоже. «$ .extend (opts, options)» - это то, что я имел в виду. Позор =) Работает сейчас. – BadZen