2015-04-17 240 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

當你從then回調不return什麼,它假定同步操作,去解決與結果(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