2015-04-17 2 views
5

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

Что мне не хватает? Я смущен тем, как вы должны использовать решение, и о том, как вы можете использовать обещание в рамках другого обещания.

Я не мог найти ничего, что помогло в Интернете.

В следующем примере я в основном загружаю кучу файлов, для каждого файла я получаю blob, и я хочу передать этот blob в программу чтения файлов.

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

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

var list = []; 
var urls = this.files; 

urls.forEach(function(url, i) { 
    list.push(
     fetch(url).then(function(response) { 
      response.blob().then(function(buffer) { 

       var promise = new Promise(
        function(resolve) { 

         var myReader = new FileReader(); 
         myReader.addEventListener('loadend', function(e) { 
          // some time consuming operations 
          ... 
          window.console.log('yo'); 
          resolve('yo'); 
         }); 

         //start the reading process. 
         myReader.readAsArrayBuffer(buffer); 
        }); 

       promise.then(function() { 
        window.console.log('smooth'); 
        return 'smooth'; 
       }); 

      }); 
     }) 
    ); 
}); 

... 

// run the promise... 
Promise 
    .all(list) 
    .then(function(message){ 
     window.console.log('so what...?'); 
    }) 
    .catch(function(error) { 
     window.console.log(error); 
    }); 

ответ

18

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

Вы должны return обещания от каждой асинхронной функции, в том числе then обратных вызовов, которые вы хотите получить прикованы.

В частности, код должен стать

var list = this.files.map(function(url, i) { 
//     ^^^^ easier than [] + forEach + push 
    return fetch(url).then(function(response) { 
     return response.blob().then(function(buffer) { 
      return new Promise(function(resolve) { 
       var myReader = new FileReader(); 
       myReader.addEventListener('loadend', function(e) { 
        … 
        resolve('yo'); 
       }); 
       myReader.readAsArrayBuffer(buffer); 
      }).then(function() { 
       window.console.log('smooth'); 
       return 'smooth'; 
      }); 
     }) 
    }); 
}); 

или даже лучше, flattened:

var list = this.files.map(function(url, i) { 
    return fetch(url).then(function(response) { 
     return response.blob(); 
    }).then(function(buffer) { 
     return new Promise(function(resolve) { 
      var myReader = new FileReader(); 
      myReader.addEventListener('loadend', function(e) { 
       … 
       resolve('yo'); 
      }); 
      myReader.readAsArrayBuffer(buffer); 
     }); 
    }).then(function() { 
     window.console.log('smooth'); 
     return 'smooth'; 
    }); 
}); 
+0

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

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