2016-12-29 7 views
0

У меня есть функция, которая возвращает обещание (используя Q), и уведомления, похоже, не происходят в нужное время. OnFulfilled и onRejected callback работают по назначению, но обратный вызов прогресса не срабатывает до тех пор, пока async.whilst() не закончит работу и не разобьет все сразу.Deferred.notify() внутри async.whilst() не вызывает обработчик хода до обратного вызова

Это функция

function generateSentences(data, num, options) { 
    var deferred = Q.defer(); 
    const markov = new Markov(data, options); 
    markov.buildCorpus() 
     .then(() => { 
      var count = 0; 
      async.whilst(
       function() { return count < num; }, 
       function (callback) { 
        markov.generateSentence() 
         .then(result => { 
          console.log("Count: " + count); 
          deferred.notify(count/num); //update progress 
          count++; 
          callback(null); 
         }, (err) => { 
          deferred.reject(err.toString()); 
          count++; 
         }); 
       }, 
       function (err, n) { 
        //PROGRESS EVENTS DON'T HAPPEN UNTIL HERE 
        deferred.resolve(generatedSentences); //finish 
       } 
      ); 
     }, (err) => console.log(err)); 
    return deferred.promise; 
} 

и это использует обещание

function generateScript() { 
    fs.readdir(parser.videoBasePath, function (err, files) { 
     parseFiles(files, parser.parse).then((a) => { 
      console.log("Total Lines: " + fullScript.length + "\n"); 
      fullScript = _.shuffle(fullScript); 
      markov.generateSentences(fullScript, 20).then((data) => { 
       console.log(data); 
      }, (err) => { 
       console.log(err); 
      }, (progress) => { 
       console.log(progress); 
      }); 
     }); 
    }); 
} 

Я читал некоторые темы, как this говоря мне нужно обернуть SetTimeout вокруг уведомит(), но он, кажется, ничего не влияет.

+0

Для диагностики, если вы регистрируете обратный вызов прогресса внутри 'generateSentences()' instanti после создания 'отложенных', он ведет себя одинаково или иначе, чем ваш существующий обратный вызов? –

+0

Возможно, именно поэтому смешивание обещаний и асинхронных задач считается «плохой вещью» * –

+0

@ Roamer-1888, просто попробовал это, он ведет себя так же, как и существующий обратный вызов. Я не знал, что смешение обещаний и асинхронная работа - плохая практика , это моя первая попытка проекта nodejs. Тем не менее, я попытался найти другое решение из одного из ответов, которое устраняет потребности в async, но все еще страдает той же проблемой. –

ответ

0

Я читал, что Promises + async.js не смешиваются (но не могут найти ничего, чтобы сказать так много!), И я не могу понять, почему это должно быть проблемой в этом случае если честно

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

function generateSentences(data, num, options) { 
    var deferred = Q.defer(); 
    const markov = new Markov(data, options); 
    const genSentence = count => markov.generateSentence() 
     .then(result => { 
      console.log("Count: " + count); 
      deferred.notify(count/num); //update progress 
      if (count < num) { 
       return genSentence(count + 1); 
      } 
     }); 
    markov.buildCorpus() 
     .then(() => genSentence(0)) 
     .then(() => deferred.resolve(generatedSentences)) //finish 
     .catch(err => deferred.reject(err.toString())); 
    return deferred.promise; 
} 

по крайней мере, код (на мой взгляд) немного чистых в любом случае

+0

Определенно чище, спасибо. Я попытался решить ваше решение [he] (https://gist.github.com/anonymous/bad9c379a371a9529eff8033ce22cfa9), но я все еще, похоже, получаю ту же проблему. Одна вещь, которую я заметил, - это если я прокомментирую строку «return genSentence», чтобы получить только цикл для запуска один раз, обратный вызов прогресса работает правильно. Это заставляет меня полагать, что notify() не нравится рекурсивный характер того, как мы его реализовали, и как async.js реализует его? –

+0

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

+0

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