链接承诺链

时间:2017-04-21 06:26:40

标签: javascript promise

我有一个工作承诺链:

function startSync(db) {
  var promise = new Promise(function(resolve, reject) {

    syncCats(db)
      .then(syncTrees(db))
      .then(syncCars(db))
      ...  
      .then(resolve());
  });
return promise;
}

这很有效。它执行每个函数调用,等待每个函数调用完成,然后再触发另一个函数调用。每个函数都返回一个promise,如下所示:

function syncCaesar(db) {
  var promise = new Promise(resolve, reject) {
    // do aysnc db calls, and whatnot, resolving/rejecting appropriately
  }
return promise;
}

我需要按顺序在一系列数据库上运行此链。 我在这里尝试了其他解决方案,但是它们会同时触发syncCats()

例如:

var promise = Promise.resolve();
dbs.forEach(function(db) {
  promise = promise.then(startSync(db));
}

同时触发syncCats(db[0])syncCats(db[1])

编辑:

执行startSync(dbs[0]).then(startSync(dbs[1]));行为相同。

Edit2:也执行相同的操作:

dbs.forEach(function(db) {
  promise = promise.then(function() {
    return startSync(db);
  }
}

3 个答案:

答案 0 :(得分:3)

正在调用 startSync,然后将其返回值传递给then。所以很自然地,如果你这样做两次,它将并行启动两次。

相反,传入一个不调用startSync的函数,直到它被调用:

var promise = Promise.resolve();
dbs.forEach(function(db) {
  promise = promise.then(function() { startSync(db); });
});

或与ES2015:

let promise = Promise.resolve();
dbs.forEach(function(db) {
  promise = promise.then(_ => startSync(db));
});

另外,有关startSync

的三件事情
  1. 它并行启动所有操作,而不是按顺序启动
  2. 展示承诺创建反模式startSync没有理由创造新的承诺;它已经它可以使用的承诺
  3. 确保其分辨率值为undefined
  4. 如果您真的希望这些操作并行运行,我建议您更明确地说明:

    function startSync(db) {
      return Promise.all([
        syncCats(db),
        syncTrees(db),
        syncCars(db)
      ])
      .then(_ => undefined); // This does #3
    }
    

    ...但你也可以做到避免反模式:

    // Still run in parallel!
    function startSync(db) {
      return syncCats(db)
        .then(syncTrees(db))
        .then(syncCars(db))
        .then(_ => undefined); // Does #3
    }
    

    如果你想让它们顺序,你需要传递函数,而不是调用它们的结果:

    function startSync(db) {
      return syncCats(db)
        .then(_ => syncTrees(db))
        .then(_ => syncCars(db))
        .then(_ => undefined);  // Again, does #3
    }
    

    如果您syncCatssyncTreessyncCars通过db解决了承诺,请执行以下操作:

    function syncCats(db) {
        return startSomethingAsync().then(_ => db);
    }
    

    ......那么它可能是:

    function startSync(db) {
      return syncCats(db)
        .then(syncTrees)
        .then(syncCars)
        .then(_ => undefined);  // Only here for #3
    }
    

    ...因为每个人都会收到db作为第一个参数。

    最后,如果您不需要强制undefined作为承诺解析值,我建议从上面删除该部分。 : - )

答案 1 :(得分:0)

感谢T.J和Jaromanda,我能够通过修复startSync()的解决方法来解决这个问题:

function startSync(db) {
  var promise = new Promise(function(resolve, reject) {

   syncCats(db)
      .then(syncTrees(db)) // not correct way to call, see below
      .then(syncCars(db))
      ...  
      .then(function() { resolve(); });
  });
 return promise;
}

现在,正如T.J指出的那样,调用每个.then的方式都是不正确的。他在答案中解释得更好。我被一些被误解的数据库层排队所挽救。 <{1}}和syncTrees() 并行运行。

答案 2 :(得分:-1)

如果我理解正确的话,你将拥有一个数据库阵列,并且你想逐个同步它们,即同步dbs [0],一旦完全同步dbs [1],依此类推。如果这是正确的,你可以做这样的事情。

var syncMultipleDBs = (dataBases) {
    var db = dataBases.shift();
    if (!db) {
        return;
    }
    startSync(db).then(syncMultipleDBs.bind(null, dataBases));
};

syncsyncMultipleDBs(dbs.slice());

我希望这会有所帮助。