如何将一个 Promise 的 resolve() 转移到另一个 Promise?

4
假设我有一个名为“JsonEditor”的模块(只是举个例子),其中包含3个函数:get()、setProperty() 和 save()。
以下是代码(问题在下面):
var fs   = require('fs')
  , q    = require('q');

var jsonEditorModule = (function() {
    return {
        get: function(jsonPath) {
            // ...
        },

        save: function(jsonObject, jsonPath) {
            var qJson = q.defer();

            var jsonContent = JSON.stringify(jsonObject, null, 2);

            fs.writeFile(jsonPath, jsonContent, function(err) {
                if(err) {
                    qJson.reject(err);
                }
                else {
                    qJson.resolve();
                }
            });

            return qJson.promise;
        },

        setProperty: function(prop, value, jsonPath) {
            var self = this;
            var qJson = q.defer();

            this.get(jsonPath)
            .then(
                function(jsonObject) {
                    // Set the property
                    jsonObject[prop] = value;

                    // Save the file
                    self.save(jsonObject, jsonPath)
                    .then(
                        function() {
                            qJson.resolve();
                        },
                        function() {
                            qJson.reject();
                        },
                    );
                }
            );

            return qJson.promise;
        },
    };
})();

module.exports = jsonEditorModule;

在setProperty()函数中,save()之后看到then()了吗?

这看起来很傻,对吧?

我需要手动解决(resolve)和拒绝(reject)我的Promise吗? 我不能只是将save()的行为传递给我的setProperty() Promise吗?

希望问题足够清楚(并且不太傻)。

谢谢。


看看这里,看看你能否重新设计你的调用结构来设置一个链式回调。https://dev59.com/32jWa4cB1Zd3GeqPrYny - Steve Mitcham
2个回答

2

看起来很愚蠢,对吧?我需要手动使用resolve()reject()来处理我的promise吗?

是的,事实上这有一个专门的名称:手动解决/拒绝一个额外的promise被称为愚蠢的延迟反模式

我能不能将save()的行为直接转移到setProperty()的promise中呢?

是的,这很容易实现,并且内置在then方法中:调用.then()返回一个新的promise,用于回调函数的return值,即使该值被隐藏在一个promise中也可以。

var jsonEditorModule = {
    get: function(jsonPath) {
        // ...
    },
    save: function(jsonObject, jsonPath) {
        return Q.ninvoke(fs, "writeFile", jsonPath, JSON.stringify(jsonObject, null, 2));
    },
    setProperty: function(prop, value, jsonPath) {
        return this.get(jsonPath).then(function(jsonObject) {
//      ^^^^^^
            // Set the property
            jsonObject[prop] = value;
            // Save the file
            return this.save(jsonObject, jsonPath);
//          ^^^^^^
        }.bind(this));
    }
};

2
您想要实现的内容在这里描述:链接,基本上,如果处理程序返回一个Promise(让我们称其为innerPromiseFromHandler),则将执行先前Promise上定义的.then的处理程序,当innerPromiseFromHandler获得解析值时:

var jsonEditorModule = (function() {
  return {
    get: function(jsonPath) {
      return Q.delay(1000).then(function () {
        document.write('get...<br/>');
        return 'get';
      });
    },

    save: function(result) {
      return Q.delay(1000).then(function () {
        document.write('save...<br/>');        
        return result + ' save';
      });
    },

    setProperty: function(prop, value, jsonPath) {
      return this.get(jsonPath)
        .then(function(result) {
          return jsonEditorModule.save(result);
        });
    }
  };
})();
      
jsonEditorModule
  .setProperty()
  .then(function (result) {    
    document.write(result + ' finish');
  })
<script src="http://cdnjs.cloudflare.com/ajax/libs/q.js/0.9.2/q.js"></script>


jsonEditorModule 的声明放在 IIFE 之外基本上违背了 IIFE 的初衷。你应该在内部声明并返回它。 - JLRishe
即使这是通过require()加载的CommonJS模块?我没有复制文件末尾的module.exports = jsonEditorModule; - Maslow
谢谢Mauricio。这非常清晰(而且更好的是,没有傲慢)。 - Maslow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接