2016-09-15 4 views
0

Ниже приведенный ниже нефункциональный пример должен объяснить, что я пытаюсь сделать, я просто не понимаю шаблон, который мне нужно использовать для его выполнения. Я попробовал поиск в Google, чтобы понять опрос и отложить, но я не мог найти ничего, что мог бы понять.

У меня есть функция, которая опроса API, и я хочу дождаться, пока этот опрос вернет ожидаемый результат (ожидая, что конечная точка укажет, что что-то изменилось), прежде чем продолжить мою основную функцию. Что я делаю не так?

Edit: Я хотел бы добавить, что КАЖЕТСЯ пойти не так с кодом ниже, что даже если deferred.resolve() в конечном итоге получает называется, кажется, что это не то же самое deferred, что получил вернулся, так что when никогда не активируется в main(). Я предполагаю, что это связано с таймаутом, то есть deferred получить clobbered на первом повторе. Это мое предположение, так или иначе.

function pollAPI() { 
    var deferred = $.Deferred(); 

    $.ajax({                 
     url: url,          
     contentType: 'application/JSON',          
     method: 'GET'               
    }).done(function(data){                                
     if (!desiredResult) {             
      setTimeout(function() {           
       pollAPI();        
      }, 1000);              
     } else {                
      deferred.resolve(); 
     }                                   
    }).error(deferred.reject());            

    return deferred.promise(); 
} 

function main() { 
    $.when(pollAPI()).then(function() { 
     // do something now that the API has returned the expected result 
    }); 
+0

каждый вызов pollAPI не создает новый отложенный, ничего получает затерт - попробуйте 'deferred.resolve (pollAPI())' в SetTimeout –

+0

Wouldn» t, что приводит к тому, что первая отсрочка будет разрешаться, тем самым вызывая «когда», даже если она не готова? – fildred13

+0

Да, это решит еще нераскрытое обещание - так что не должно быть проблемой - см. Раздел 2.3 в [Promise/A + specification] (https://promisesaplus.com/) - jquery, возможно, следует этой спецификации, но там являются значительными отклонениями от спецификации Promise/A + в некоторых более ранних версиях jQuery –

ответ

2

Вы можете использовать цепочки последующих вызовов функции pollAPI() создать единое обещание, что есть другие прикованные на него. Это будет выглядеть так:

// utility function to create a promise that is resolved after a delay 
$.promiseDelay = function(t) { 
    return $.Deferred(function(def) { 
     setTimeout(def.resolve, t); 
    }).promise(); 
} 

function pollAPI() { 
    return $.ajax({ 
     url: url, 
     contentType: 'application/JSON', 
     method: 'GET' 
    }).then(function(data) { 
     // some logic here to test if we have desired result 
     if (!desiredResult) { 
      // chain the next promise onto it after a delay 
      return $.promiseDelay(1000).then(pollAPI); 
     } else { 
      // return resolved value 
      return someValue; 
     } 
    }); 
} 

function main() { 
    pollAPI().then(function(result) { 
     // got desired result here 
    }, function(err) { 
     // ended with an error here 
    }); 
} 

Это имеет следующие преимущества:

  1. Нет ненужного обещание не создано, чтобы попытаться окружить вызов AJAX, что уже есть обещание. Это позволяет избежать одного из common promise anti-patterns.
  2. Последующие звонки в API просто связаны с оригинальным обещанием.
  3. Нет необходимости использовать $.when(), когда у вас есть только одно обещание. Вы можете просто использовать .then() прямо на нем.
  4. Все ошибки автоматически перколяются обратно к первоначальному обещанию.
  5. Это использует ES6-стандарт .then() (который фактически становится более законным стандартом в jQuery 3.x - хотя он работает в jQuery 1.x и 2.x со своими нестандартными причудами), что делает эту логику более совместимой с другие перспективные асинхронные функции.

Кроме того, ряд других Retry идей здесь: Promise Retry Design Patterns

+0

Это более или менее работаю, и я ценю ссылки. Я работаю над ними, чтобы лучше понять шаблон. Единственная часть, о которой я до сих пор смущаюсь, это «return someValue». Если я устанавливаю someValue на foobar перед возвратом, а затем 'console.log (result)', то 'undefined' выводится на консоль.Я что-то неправильно понимаю о возвращении ценностей через цепочку обратно в main()? – fildred13

+0

@ fildred13 - Вы должны были бы показать мне (возможно, как дополнение к вашему вопросу) именно то, что вы пытаетесь, потому что 'return someValue' (где вы фактически ставите реальную ценность вместо' someValue') будет распространять назад разрешенное значение к оригинальному обещанию и будет отображаться в 'main()' как аргумент 'result', если вы используете код, как я показал. – jfriend00

+0

О, я вижу, что не так - для меня 'then' pollAPI() не вызывается, даже когда я возвращаю someValue'. В принципе, функция pollAPI() заканчивается, но 'then' никогда не вызывается. Мысли? – fildred13

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

  • Нет связанных вопросов^_^