我有一个生成电子邮件的javascript函数。
如果有电子邮件的附件,我会通过附件循环播放,每次上传一个附件到Dropbox而不是实际附加附件我附加到电子邮件正文的Dropbox链接到文件
(相关代码用反斜杠包装)
self.email = function (action, contact) {
var emailTo = contact.email();
var attachment = "";
var lineBreak = "%0D%0A";
var signature = uvm.user().fullName()
var body;
var dropboxLink = "";
switch (action) {
case "a":
body = "aaaa";
break;
case "b": case "c":
body "bbbccc";
break;
//////////The piece of code that I'm working on//////////
default:
$.each(self.checkedDocs(), function (key, doc) {
self.service.getDropboxLink(doc, function (result) {
dropboxLink = result;
attachment += lineBreak + doc.documentDescription() + ": " + dropboxLink;
});
});
body = "Please click on the link(s) below to view your document(s): "
//////////End//////////
}
attachment = attachment ? attachment + lineBreak + lineBreak : lineBreak;
body += lineBreak + attachment + signature;
window.location.href = "mailto:" + emailTo + "?subject=" + self.subject() + "&body=" + body;
}
这是getDropboxLink
函数:
self.getDropboxLink = function (doc, callback) {
$.ajax({
url: "/API/dropbox/DropboxUpload",
type: "POST",
data: ko.toJSON(doc),
contentType: "application/json",
success: function (data) {
callback(data);
}
});
}
此代码无法正常运行,如果案例为default
并且有电子邮件附件,则电子邮件之前 我从API获取Dropbox链接。
我可以将async=false
添加到POST请求中,这样可以解决问题,但不推荐使用async=false
。
我认为我应该使用回调或承诺来执行此操作,但由于生成电子邮件的代码部分属于cases
的所有switch
和只在default
部分调用API。
如果action
为default
我需要:
attachment = attachment ? attachment + lineBreak + lineBreak : lineBreak;
body += lineBreak + attachment + signature;
window.location.href = "mailto:" + emailTo + "?subject=" + self.subject() + "&body=" + body;
在完成此操作后发生:
$.each(self.checkedDocs(), function (key, doc) {
self.service.getDropboxLink(doc, function (result) {
dropboxLink = result;
attachment += lineBreak + doc.documentDescription() + ": " + dropboxLink;
});
});
如果操作为a
或b
或c
,则无关紧要。
我希望我能说清楚。有什么建议吗?
非常感谢任何帮助。
答案 0 :(得分:1)
您可以通过计算仍需要获取的异步回复的数量来解决异步问题,并且只有在达到零时才会继续生成输出。如果将输出生成代码放在(嵌套)函数中,则可以同步调用它(对于非默认情况)和异步调用(对于默认情况,当计数器为零时):
self.email = function (action, contact) {
var lineBreak = "%0D%0A";
function openEmail(body, attachment) {
attachment = attachment ? attachment + lineBreak + lineBreak : lineBreak;
body += lineBreak + attachment + uvm.user().fullName();
window.location.href = "mailto:" + contact.email() + "?subject=" + self.subject() + "&body=" + body;
}
switch (action) {
case "a":
openEmail("aaaa");
break;
case "b": case "c":
openEmail("bbbccc");
break;
default:
var attachment = "",
docs = self.checkedDocs(),
count = docs.length;
if (!count) { // treat the case where there are no attachments
openEmail("No attachments");
break;
}
$.each(docs, function (key, doc) {
self.service.getDropboxLink(doc, function (dropboxLink) {
attachment += lineBreak + doc.documentDescription() + ": " + dropboxLink;
if (--count == 0) { // last one:
openEmail("Please click on the link(s) below to view your document(s): ", attachment);
}
});
});
}
}
您可以查看promises,它可以很好地处理异步任务。您将首先更改函数 getDropboxLink ,以便它返回$.ajax()
调用的返回值,这是一个jQuery承诺。不再需要回调,也不需要成功处理程序。
然后在电子邮件函数中,您将在每个承诺上调用then
方法以返回格式化的附件文本。 then
方法也返回一个promise,所有这些promise都可以映射到一个数组中。使用$.when
,您可以在完成所有这些承诺后获得信号。您在其回调中获得的参数将是您在then
回调中返回的任何内容。
以下是进行这些调整的代码:
self.email = function (action, contact) {
var lineBreak = "%0D%0A";
function openEmail(body, attachment) {
attachment = attachment ? attachment + lineBreak + lineBreak : lineBreak;
body += lineBreak + attachment + uvm.user().fullName();
window.location.href = "mailto:" + contact.email() + "?subject=" + self.subject() + "&body=" + body;
}
switch (action) {
case "a":
openEmail("aaaa");
break;
case "b": case "c":
openEmail("bbbccc");
break;
default:
var docs = self.checkedDocs();
if (!docs.length) { // treat the case where there are no attachments
openEmail("No attachments");
break;
}
$.when.apply($, docs.map(function (doc) {
return self.service.getDropboxLink(doc).then(function (dropboxLink) {
return lineBreak + doc.documentDescription() + ": " + dropboxLink;
});
})).done(function() {
var attachment = [].join.call(arguments, '');
openEmail("Please click on the link(s) below to view your document(s): ", attachment);
});
}
}
self.service.getDropboxLink = function (doc) {
return $.ajax({
url: "/API/dropbox/DropboxUpload",
type: "POST",
data: ko.toJSON(doc),
contentType: "application/json"
});
}
注意:您的代码同时引用了self.service.getDropboxLink
和self.getDropboxLink
(没有服务)。请根据您的实际情况调整。
答案 1 :(得分:0)
首先建议使用promise.all,但我将以旧方式解释。
window.location.href = xxx
将在您获得Dropbox链接之前执行,因此首先您需要知道有多少异步调用,并且在每个完成的回调中,检查是否所有任务都已完成
var results = arr.map((x,index)=>{
$.ajax(url,data,function(){
results[index] = true
if(results.every((x)=>x)){
location.href=xxxx
}
})
return false
})