请考虑以下以串行/顺序方式读取文件数组的代码.readFiles返回一个promise,只有在按顺序读取所有文件后才会解析.
var readFile = function(file) {
... // Returns a promise.
};
var readFiles = function(files) {
return new Promise((resolve, reject) =>
var readSequential = function(index) {
if (index >= files.length) {
resolve();
} else {
readFile(files[index]).then(function() {
readSequential(index + 1);
}).catch(reject);
}
};
readSequential(0); // Start!
});
};
Run Code Online (Sandbox Code Playgroud)
上面的代码可以工作,但我不喜欢按顺序进行递归递归.是否有一种更简单的方法可以重写此代码,以便我不必使用我的奇怪readSequential功能?
最初我试图使用Promise.all,但这导致所有readFile调用同时发生,这不是我想要的:
var readFiles = function(files) {
return Promise.all(files.map(function(file) {
return readFile(file);
}));
};
Run Code Online (Sandbox Code Playgroud) 我在下面有以下承诺链,它看起来很混乱(每个_create*函数返回一个承诺):
return new Promise(function (resolve, reject) {
_this.database.transaction(function (t) {
_this._createExternalAccount(payment, t)
.then(function (externalAccount) {
return _this._createExternalTransaction(externalAccount, payment, t)
.then(function (externalTransaction) {
return _this._createAddress(externalAccount, payment, t)
.then(function (address) {
return _this._createTransaction(address, payment, t)
.then(function (transaction) {
return _this._createGatewayTransaction(externalTransaction, transaction, payment, t)
.then(function (gatewayTransaction) {
t.commit();
resolve(bridgePayment);
});
});
});
});
})
.error(function (bridgePayment) {
t.rollback();
reject(bridgePayment);
});
});
Run Code Online (Sandbox Code Playgroud)
我知道我可以使用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 …Run Code Online (Sandbox Code Playgroud) 我无法绕开承诺.我正在使用Google Earth API对地址进行"浏览".游览只是一个持续大约一分钟的动画,当一个完成时,下一个应该开始.
这是我的游览功能:
var tourAddress = function (address) {
return tourService.getLatLong(address).then(function (coords) {
return tourService.getKmlForCoords(coords).then(function (kml) {
_ge.getTourPlayer().setTour(kml);
_ge.getTourPlayer().play();
var counter = 0;
var d = $q.defer();
var waitForTour = function () {
if (counter < _ge.getTourPlayer().getDuration()) {
++counter;
setTimeout(waitForTour, 1000);
} else {
d.resolve();
}
};
waitForTour();
return d.promise;
});
});
}
Run Code Online (Sandbox Code Playgroud)
这看起来效果很好.它启动动画并返回一个在动画完成时解析的promise.现在我有一个地址数组,我想做一个foreach他们:
$scope.addresses.forEach(function (item) {
tourAddress(item.address).then(function(){
$log.log(item.address + " complete");
});
});
Run Code Online (Sandbox Code Playgroud)
当我这样做时,它们都会同时执行(Google Earth会为最后一个地址执行动画)并且它们都会同时完成.如何在上一个完成之后将它们链接起来?
UPDATE
我用@ phtrivier的帮助来实现它:
$scope.addresses.reduce(function (curr,next) {
return curr.then(function(){
return tourAddress(next.address)
});
}, Promise.resolve()).then(function(){ …Run Code Online (Sandbox Code Playgroud) 我试图链接一系列Promises 以便第二个承诺将在第一个解决之后开始,依此类推。我不明白我怎么不能让它正常工作。
这是我的演示代码:
const promise1 = new Promise((resolve, reject) => { setTimeout(resolve, 5000, 'a'); });
const promise2 = new Promise((resolve, reject) => { setTimeout(resolve, 5000, 'b'); });
const promise3 = new Promise((resolve, reject) => { setTimeout(resolve, 5000, 'c'); });
promise1.then(val => {
console.log('promise 1', val);
promise2.then(val2 => {
console.log('promise 2', val2);
promise3.then(val3 => {
console.log('promise 3', val3);
});
});
});
Run Code Online (Sandbox Code Playgroud)
所以我对这段代码的期望是这样的:
--- 5 seconds passes ---
// console outputs: 'promise 1a'
--- 5 seconds passes ---
// console …Run Code Online (Sandbox Code Playgroud)