异步与它无关。一旦进入成功回调,异步部分已经完成。问题在于,在第一次更改有时间加载之前,您要再次更改窗口位置。换句话说,这与异步问题完全相反;问题是这段代码是同步的,运行速度太快。
但是,这里的方法是有缺陷的。它可能工作,如果浏览器被迫下载文件,因为那么第一次更改为window.location
本身不会导致浏览器视图更改。由于PDF通常是浏览器可浏览的类型,但这并不能保证。无论如何,你仍然有同样的问题需要延迟第二个电话,直到第一个电话得到响应,这基本上是不可能的。这种类型的事情没有内置的事件,所以最好你可以做的就是使用setTimeout
延迟1-2秒,只是希望这是足够的时间来获得第一个响应。即使这样,如果它花费更长时间,您的代码也会再次中断。换句话说,它会变得非常脆弱。
简单的事实是,这仅仅不是HTTP的工作方式。你基本上试图为单个请求返回两个响应,这是不可能的。这是一种巧妙的方式,可以避开协议中固有的限制,我会给你的,但最终还是不够。
所有这一切说,你可以实际上使通过HTML5文件API和AJAX这种情况发生,但你的解决方案,然后将只与现代浏览器兼容(基本上一切,除了IE 10和下)。如果你不需要支持较低版本的IE,那么你可以使用下面的代码来代替:
function (response) // success callback
{
$http.get('@Url.Action("PdfCreator", "someController")?Id=' + $scope.id').then(
function (response) // success callback
{
var a = document.createElement('a');
var url = window.URL.createObjectURL(response.data);
a.href = url;
a.download = 'myfile.pdf';
a.click();
window.URL.revokeObjectURL(url);
window.location = '@Url.Action("Index","AnotherController")';
},
function (response) // failure callback
{
alert(response.statusText);
}
);
},
的秘诀是在获取通过AJAX的PDF,然后创建一个对象URL出来的PDF数据。然后,您可以使用它在DOM中创建一个锚点元素并动态“点击”它以提示下载。但是,需要注意的是,我还没有尝试过使用Angular,所以我不确定$http
是否支持获取二进制响应。我知道jQuery,你只需告诉它,XHR对象的响应类型是'blob',但我不确定你是否可以或如何使用Angular做同样的事情。作为替代,您可以直接使用XMLHttpRequest
直接用于此特定AJAX,并且只需设置xhr.responseType = 'blob'
即可。