2016-12-01 2 views
0

Проявив fs-extra, я понимаю, что я могу использовать then для доступа к файлам. I Угадай там есть механизм, который после того, как он получит файл, он знает, чтобы перейти к следующей ссылке в цепочке then. Однако, следующий then Я только что поставил простой цикл. А следующий просто печатает строку на консоли. Я ожидал, что какой-то объект Promise будет возвращен для его перемещения по цепочке. Что необходимо для продолжения этой цепи? Например, если я вставляю setTimeout в течение секунды, цепочка продолжается и выводится из строя.Как сибирская птица знает, чтобы перейти к следующей «тогда» в этой цепочке?

var Promise = require('bluebird') 
    , fs = Promise.promisifyAll(require('fs-extra')) 

fs.readdirAsync(dir) 
    .bind(this) 
    .then((files) => { 
     this.files = files; 
    }) 
    .then(() => { 
     var num = 10000 
     this.files.forEach((file, index, array) => { 
      for(i = 0; i < num; i++){ 
       console.log(num*i); 
      } 
     }); 
    }) 
    .then(() => { 
     console.log('middle of it'); 
    }) 
    .then(() => { 
     console.log('done with it'); 
    }) 
    .catch((err) => { 
     console.log(err); 
    }); 
+1

Это то же самое, как делать что-то вроде 'Promise. решимость (нуль) .then (независимо) '. Если в обещании нет реальной задачи, обещание немедленно решается. – m0meni

+0

@ AR7 Как бы вы решили добавить таймаут в этом случае? [Документы для '.timeout'] (http://bluebirdjs.com/docs/api/timeout.html) заставляют выглядеть так, как будто вы можете просто поставить' .timeout (1000) 'между' then', но это не работает. – 1252748

+0

Вам может понравиться это, http://www.mattgreer.org/articles/promises-in-wicked-detail/ –

ответ

2

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

Ключ в том, что p.then() возвращает новое обещание, которое само по себе разрешено, когда выполнено p.then(), чтобы затем запустить следующий шаг в цепочке p.then().then() и так далее.

Имейте в виду, что .then() обработчик может сделать одну из четырех вещей:

  1. Возврат ничего (то же самое, как возвращение undefined).
  2. Вернуть значение
  3. Возвращение обещание
  4. Бросьте исключение

Для первых двух (возвращающей значение), то это просто означает, что .then() обработчик выполняется, а затем следующий в цепочке может быть запущен.

При возвращении обещания, это обещание связано с обработчиками .then(), поэтому его можно контролировать. Если/когда он разрешается, цепочка продолжается. Если/когда он отклоняется, цепь отклоняется. Обещание, которое возвращается, уже может быть разрешено или отклонено или может быть разрешено или отклонено в будущем, нет значимой разницы в поведении. Если возвращенное обещание никогда не будет разрешено или отклонено, цепочка обещаний застопорилась и не будет продолжаться до тех пор, пока она не будет разрешена или отвергнута (как и любое обещание).

Если обработчик .then() выбрасывает исключение, это улавливается оберткой .then(), и оно автоматически преобразуется в отклоненное обещание, за исключением причины отклонения.

Например, если я вставлял setTimeout на секунду, то цепочка продолжается и печатается не по порядку.

Вы не можете эффективно использовать setTimeout() самостоятельно, чтобы отложить цепочку обещаний. Вместо этого вам нужно вернуть обещание от обработчика .then(), который разрешен после некоторого времени таймаута. Bluebird имеет .delay(x), который делает это за вас.

Или, вы можете написать его самостоятельно, если не используется Bluebird:

function delay(t) { 
    return new Promise(function(resolve) { 
     setTimeout(resolve, t); 
    }); 
} 

fn().then(function() { 
    // delay promise chain by 1000ms 
    return delay(1000); 
}).then(function() { 
    // promise chain continues here 
}); 

Или, с Bluebird обещаниями, это так просто, как:

fn().delay(1000).then(function() { 
    delayed promise chain continues here 
}); 
+0

Я ошибаюсь, думая, что он всегда возвращает новые обещания, такие как 'Promise.resolve (undefined | value)' или 'Promise.reject' on throws, обещание возвращается ?? – Annarfych

+0

@Annarfych - Что всегда возвращает новое обещание? '.then()' всегда возвращает новое обещание. Это новое обещание, которое само по себе разрешено или отклонено после выполнения обработчика '.then()' предыдущего обещания, и любое обещание, которое оно могло бы вернуть, выполнило. – jfriend00

+0

Да, я говорю о 'то'. Если это так, вы можете упростить объяснение, чтобы любое возвращаемое значение конвертировалось, чтобы обещать, когда действуют следующие действия 'then' или' catch'. – Annarfych