単純な約束を超えるものは、たいてい当惑します。この場合、N 個のオブジェクトに対して連続して 2 つの非同期呼び出しを行う必要があります。まず、ディスクからファイルをロードし、そのファイルをメール サーバーにアップロードする必要があります。私は 2 つのアクションを一緒に実行することを好みますが、すべての読み取りを最初に実行し、次にすべてのアップロードを実行することで機能するようになりました。以下のコードは機能しますが、もっとうまくできると思わずにはいられません。私が理解できないことの 1 つは、なぜ when.all が拒否しないのかということです。ドキュメントの私の解釈は、約束の1つが拒否された場合、.allが拒否されることを暗示しているようです。エラーをテストするために、下位の解決をコメントアウトしました。エラーがなければ、問題なく動作し、理にかなっているように見えます。
mail_sendOne({
from: 'greg@',
to: 'wilma@',
subject: 'F&B data',
attachments: [
{name: 'fred.html', path: '/fred.html'},
{name: 'barney.html', path: '/barney.html'}
]
})
.done(
function(res) {
console.log(res)
},
function(err) {
console.log('error ', err);
}
)
function mail_sendOne(kwargs) {
var d = when.defer();
var promises = [], uploadIDs = [], errs = [];
// loop through each attachment
for (var f=0,att; f < kwargs.attachments.length; f++) {
att = kwargs.attachments[f];
// read the attachment from disk
promises.push(readFile(att.path)
.then(
function(content) {
// upload attachment to mail server
return uploadAttachment({file: att.name, content: content})
.then(
function(id) {
// get back file ID from mail server
uploadIDs.push(id)
},
function(err) {
errs.push(err)
}
)
},
function(err) {
errs.push(err)
}
))
}
// why doesn't this reject?
when.all(promises)
.then(
function(res) {
if (errs.length == 0) {
kwargs.attachments = uploadIDs.join(';');
sendEmail(kwargs)
.done(
function(res) {
d.resolve(res);
},
function(err) {
d.reject(err);
}
)
}
else {
d.reject(errs.join(','))
}
}
)
return d.promise;
}
function readFile(path) {
var d = when.defer();
var files = {
'/fred.html': 'Fred Content',
'/barney.html': 'Barney Content'
}
setTimeout(function() {
d.reject('Read error');
//d.resolve(files[path]);
}, 10);
return d.promise;
}
function uploadAttachment(obj) {
var d = when.defer();
setTimeout(function() {
d.reject('Upload error');
//d.resolve(new Date().valueOf());
}, 10);
return d.promise;
}
function sendEmail(kwargs) {
var d = when.defer();
setTimeout(function(){
console.log('sending ', kwargs)
}, 5);
return d.promise;
}