Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/http/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 处理嵌套承诺的最佳方式(蓝鸟)_Javascript_Promise_Bluebird - Fatal编程技术网

Javascript 处理嵌套承诺的最佳方式(蓝鸟)

Javascript 处理嵌套承诺的最佳方式(蓝鸟),javascript,promise,bluebird,Javascript,Promise,Bluebird,我有下面的承诺链,它看起来很混乱(每个\u create*函数返回一个承诺): 我知道我可以使用一些Promise函数,比如all()和join(),但这些函数似乎同时运行,而我不能这样做,因为持久化到某些表需要来自先前持久化表的字段。我希望有一些方法可以让我做如下事情,但我似乎无法找到方法: Promise.all(_this._createExternalAccount(payment, t), _this._createExternalTransaction(externalAccount

我有下面的承诺链,它看起来很混乱(每个
\u create
*函数返回一个承诺):

我知道我可以使用一些Promise函数,比如
all()
join()
,但这些函数似乎同时运行,而我不能这样做,因为持久化到某些表需要来自先前持久化表的字段。我希望有一些方法可以让我做如下事情,但我似乎无法找到方法:

Promise.all(_this._createExternalAccount(payment, t), _this._createExternalTransaction(externalAccount, payment, t), _this._createAddress(externalAccount, payment, t))
    .then(function(externalAccount, externalTransaction, address) {
        // do logic
    });

就个人而言,当依赖关系变得混乱时,我更喜欢以下方法:

var externalAccount     = Promise.join(payment, t,                                   createExternalAccount),
    externalTransaction = Promise.join(externalAccount, payment, t,                  createExternalTransaction),
    address             = Promise.join(externalAccount, payment, t,                  createAddress),
    transaction         = Promise.join(address, payment,                             createTransaction),
    gatewayTransaction  = Promise.join(externalTransaction, transaction, payment, t, createGatewayTransaction);
让一切变得更干净,尽管这是一个风格的问题

如果您想在获得
gatewayTransaction
的值(当然是异步的)后做些什么,您可以:

gatewayTransaction
    .then(function (val) {
        // do stuff
    })
    .catch(function (err) {
        // do stuff
    });
这里有一个微妙的陷阱,你应该注意。承诺的定义顺序不一定是函数的调用顺序。这就是依赖项的外观:

externalAccount -----> externalTransaction -----> gatewayTransaction
                |--> address --> transaction --|
虽然这对性能有好处,但您可能希望使整个过程按顺序进行(就像回调金字塔一样)。在这种情况下,您可以编写:

var externalAccount     = Promise.join(payment, t,                                       createExternalAccount),
    externalTransaction = Promise.join(externalAccount, payment, t,                      createExternalTransaction),
    address             = Promise.join(externalAccount, payment, t, externalTransaction, createAddress),
    transaction         = Promise.join(address, payment,                                 createTransaction),
    gatewayTransaction  = Promise.join(externalTransaction, transaction, payment, t,     createGatewayTransaction);

通过将
externalTransaction
添加到
address
的依赖项中(即使不需要它的值),您可以强制它是连续的

我完全确定你在问什么,但是

  • 如果您想按顺序运行一系列承诺,那么

    需要注意的是,这不是一系列的承诺。这是一系列的函数,它们做出了承诺。这是因为承诺会立即执行,所以在需要之前无法创建承诺

  • 如果你不想把它们放到数组中,那么正常的事情就是正常地把它们链起来

    同样,让一堆函数实现回报承诺的最简单方法。那你就

    var p = firstFunctionThatReturnsAPromise()
    .then(secondFunctionThatReturnsAPromise)
    .then(thirdFunctionThatReturnsAPromise)
    .then(fourthFunctionThatReturnsAPromise)
    
    你可以很容易地把它们套起来

    function AOuterFunctionThatReturnsAPromise() {         
        var p = firstFunctionThatReturnsAPromise()
                .then(secondFunctionThatReturnsAPromise)
                .then(thirdFunctionThatReturnsAPromise)
                .then(fourthFunctionThatReturnsAPromise);
        return p;
    };
    
    现在,外部函数只是另一个返回承诺的函数,这意味着 可以应用与内部函数相同的模式

    如果这些当然可以内联的话

    var p = function() {
      return new Promise(resolve, reject) {
        DoSomethingAsync(function(err, result) {
          if (err) {
            reject();
          } else {
            resolve(result);
        };
      };
    }).then(function() {
      return new Promise(resolve, reject) {
        DoSomethingAsync(function(err, result) {
          if (err) {
            reject(err);
          } else {
            resolve(result);
        };
      };
    }).then(function() {
      var err = DoSomethingNotAsync();
      if (err) {
         return Promise.reject(err);
      } else {
         return Promise.resolve();
      }
    });
    
    等等


  • 您可能想探索链接:
    p.then().then().then().then()
    而不是嵌套。检查Bluebird
    .map()
    您可以传递
    {concurrency:N}
    ,因此它一次只执行
    N
    操作这肯定是我在讨论使用Gorgi和Petka向Bluebird添加联接时想到的。我觉得这是一个很好的风格很高兴听到,我真的很喜欢它。
    var p = function() {
      return new Promise(resolve, reject) {
        DoSomethingAsync(function(err, result) {
          if (err) {
            reject();
          } else {
            resolve(result);
        };
      };
    }).then(function() {
      return new Promise(resolve, reject) {
        DoSomethingAsync(function(err, result) {
          if (err) {
            reject(err);
          } else {
            resolve(result);
        };
      };
    }).then(function() {
      var err = DoSomethingNotAsync();
      if (err) {
         return Promise.reject(err);
      } else {
         return Promise.resolve();
      }
    });