承诺无法解决

时间:2017-06-19 22:08:04

标签: javascript node.js promise

我是节点的新手,我遇到了解决异步Promise的问题。我的承诺没有解决,我不确定我做错了什么。我仍然无法理解承诺和回调,所以任何反馈都是有帮助的。

m.index = ...         # same index with first model's m.index
m.y = Var(m.index)    # lets assume it has values or I can put with init command

2 个答案:

答案 0 :(得分:2)

至少看到三个错误:

  1. 当您点击此if语句if(! /^\..*/.test(file)){并且它未执行if块时,父承诺永远不会解决。

  2. fs.stat()上没有错误处理,因此如果您在该通话中收到错误,则忽略该错误并尝试使用错误值。

  3. 您拨打fs.readdir()时的错误处理不完整,并且会给您一个永不解决的承诺(当它应该被拒绝时)。

  4. 对于强大的解决方案,您真的不希望在同一代码中混合使用promises和callback。它会导致很多错误,特别是错误处理(因为你可以看到你至少有三个错误 - 其中两个错误处理)。

    如果您打算使用Promises,那么请宣传您在最低级别使用的异步操作,并仅使用promises来控制异步代码流。我所知道的最简单的方法是宣传相关的fs操作,就是使用Bluebird promise库及其Promise.promisifyAll()。您不必使用该库。您可以为您正在使用的异步操作手动编写promise包装器。

    以下是使用Bluebird promise库的代码版本:

    const Promise = require('bluebird');
    const fs = Promise.promisifyAll(require('fs'));
    
    function filterFiles() {
        return fs.readdirAsync(rootDir).then(function(files) {
            let fileArray = [];
            let dirArray = [];
    
            // filter out entries that start with .
            files = files.filter(function(f) {
                return !f.startsWith(".");
            });
            return Promise.map(files, function(f) {
                return fs.statAsync(f).then(function(stats) {
                    if (stats.isDirectory()) {
                        dirArray.push(f);
                    } else {
                        fileArray.push(f);
                    }
                });
            }).then(function() {
                // make the resolved value be an object with two properties containing the arrays
                return {dirArray, fileArray};
            });
        });
    }
    
    
    
    filterFiles().then(function(data) {
        res.json(data);
    }).catch(function(err) {
        // put whatever is appropriate here
        res.status(500).end();
    });
    

    通过以下更改重写/重组:

    1. 对所有异步操作使用promise
    2. 修复所有错误处理以拒绝返回的承诺
    3. 在处理任何文件之前同步过滤掉以.开头的文件(简化异步处理)。
    4. 使用Promise.map()并行处理值数组。
    5. filterFiles().then()处理程序中,处理错误
    6. 你不能res.send()一个Javascript对象,所以我使用res.json(data)代替(虽然我不确定你到底想要发送什么)。
    7. 使用更高效,更易于理解的.startsWith()替换正则表达式比较。
    8. 如果您不想使用Bluebird promise库,您可以为您使用的fs方法创建自己的promise包装器:

      fs.readdirAsync = function(dir) {
          return new Promise(function(resolve, reject) {
              fs.readdir(dir, function(err, data) {
                  if (err) {
                      reject(err);
                  } else {
                      resolve(data);
                  }
              });
          });
      }
      
      fs.statAsync = function(f) {
          return new Promise(function(resolve, reject) {
              fs.stat(f, function(err, data) {
                  if (err) {
                      reject(err);
                  } else {
                      resolve(data);
                  }
              });
          });
      }
      
      function filterFiles() {
          return fs.readdirAsync(rootDir).then(function(files) {
              let fileArray = [];
              let dirArray = [];
      
              // filter out entries that start with .
              files = files.filter(function(f) {
                  return !f.startsWith(".");
              });
              return Promise.all(files.map(function(f) {
                  return fs.statAsync(f).then(function(stats) {
                      if (stats.isDirectory()) {
                          dirArray.push(f);
                      } else {
                          fileArray.push(f);
                      }
                  });
              })).then(function() {
                  // make the resolved value be an object with two properties containing the arrays
                  return {dirArray, fileArray};
              });
          });
      }
      
      
      filterFiles().then(function(data) {
          res.json(data);
      }).catch(function(err) {
          res.status(500).end();
      });
      

答案 1 :(得分:0)

您遇到的主要问题是最外层的承诺未得到解决或拒绝。您可以通过解析Promise.all而非退回来解决此问题。

    resolve(
      Promise.all(actions)
        .then(function(resolvedTasks){
          // ... next potential issue is here
          return {dirArray: dirArray, fileArray: fileArray}
        })
    );

(我知道,有点尴尬吗?)

接下来,Promise.all解析后的返回值有点奇怪。在task功能中,您将项目推送到dirArrayfileArray,但不会在您的代码段中声明或分配这些项目。我将假设它们是此代码的范围。在这种情况下,您只需要返回所需的对象。

此外,为了使您的异步代码更具可读性,请参阅以下提示:

  • 尽量不要将回复与Promises混合
  • 使用Promise库来宣传任何限于回调的代码。示例:bluebird's promisifyAll
  • 尽可能避免嵌套回调/承诺