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