2013-09-13 4 views
0

Я пытаюсь создать основной посыл с функцией прогресса как:WinJS Promise не получает казнены

asyncCall().then(function() { 
        that.output("complete"); 
       }, 
       null, 
       function(v) { 
        that.output(v); 
       }).done(); 


function asyncCall() { 
     return new WinJS.Promise(function (complete, error, progress) { 
      progress("some progress"); 
      setTimeout(function() { 
       complete(); 
      }, 1000); 
     }); 
    } 

Я бы ожидать, что это выход «прогресс» в течение 1 секунды, а затем отобразить «полное» ; однако «прогресс» никогда не выводится. Отладка JavaScript, функция прогресса вызывается на объекте обещание, однако он получает этот код (строка 1447 из base.js) и слушатели не определено:

function progress(promise, value) { 
     var listeners = promise._listeners; 
     if (listeners) { 

Любая идея, что я пропускаю, чтобы справиться с прогрессом мероприятие?

ответ

3

Это фактически работает как запроектированный, хотя и не обязательно, как ожидалось. progress вызывается для всех текущих слушателей. Но поскольку ваш метод полностью синхронный, при первом вызове нет подключенных слушателей. В отличие от других функций Promise, это немного отличается, так как все еще можно вызвать другие функции, такие как полная и ошибка.

Вы можете увидеть это, если вы завернуты код asyncCall:

function asyncCall() { 
    return new WinJS.Promise(function (complete, error, progress) { 
     setImmediate(function() { 
      progress('hello!'); 
      setTimeout(function() { 
       complete(); 
      }, 1000); 
     }, 0); 
    }; 

} 
1

Что происходит, так это то, что вы звоните в progress() происходит синхронно с созданием нового WinJS.Promise. То есть класс WinJS.Promise получает экземпляр, и как часть его инициализации он вызывает ваш анонимный инициализатор с полными диспетчерами ошибок, ошибок и прогресса, как я их называю.

Эти диспетчеры каждый управляют массивом обработчиков, которые прикреплены к ним («слушатели»), поэтому, когда вы вызываете их, как вы делаете с progress() и complete(), они перебирают этот массив и вызовите каждый обработчик по очереди.

Однако на этом этапе выполнения никаких обработчиков не было привязано ни к чему, поскольку asyncCall еще не вернулась, и на самом деле новый WinJS.Promise еще не вернулся. Таким образом, ваш ход вызова («некоторый прогресс») происходит просто отлично, но диспетчер не имеет прикрепленных обработчиков, поэтому ничего не происходит.

Ваш обработчик получает вызов, потому что setTimeout дает поток пользовательского интерфейса, позволяя вашему инициализатору возвращаться, позволяя конструктору WinJS.Promise возвращаться, позволяя asyncCall возвращать новое обещание. Только в этот момент ваш призыв к обещанию присоединяет ваших завершенных и продвинутых обработчиков. Итак, через секунду после завершения тайм-аута вызов complete() вызывает ваш обработчик.

Короче говоря, ваш обработчик хода никогда не вызывается, потому что ваш инициатор обещаний вызывает его синхронно с созданием обещания. Попробуйте сделать что-то подобное в вашем инициализаторе:

setTimeout(function() { 
    progress("some progress"); 
}, 100); 

Это также выход, получая вас от создания обещания, таким образом, что ваш обработчик прогресс будет приложен. Вы также можете сделать setInterval для вызова прогресса каждые 100 мс, чтобы отменить интервал, когда произойдет таймаут завершения 1s. Затем вы увидите повторные вызовы обработчику хода.

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

+0

Параметр 'уведомление progress' должно быть потеряно, но если вы не можете назвать' 'complete' или error' в той же очереди строительства, что является ошибкой и должно быть сообщено. –

+0

Благодарим вас за подробное объяснение, но другой ответ предлагает полное решение, которое заставляет код работать должным образом. + 1ing. – patrickbadley

+0

Вы можете вызвать полную или ошибку во время строительства, но никто не слушает в то время, так что это просто не-op. Это не ошибка, не связанная с тем, что любой другой объект пытается поднять события во время строительства до того, как какой-либо другой код сможет подключить обработчики. Обещания являются вызывающей конструкцией более чем что-либо, поэтому полезность обещания, которое завершается, как только она построена, вызывает сомнения - почему бы просто не получить функцию, возвращающую значение? Кроме того, если вам нужно обещание с фиксированным значением, используйте WinJS.Promise.as, что намного проще. –

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