关于$q.all(Promises)结果顺序及跨域问题的技术咨询
关于Angular $q.all的结果顺序与跨域问题的解答
一、$q.all的结果顺序是否固定?
答案是肯定的,resultList的顺序完全和你传入$q.all的promises数组顺序一致,和请求实际返回的先后无关!
拿你的例子来说:
- 你先把
loadingJson('example.com/1.json')推入数组,再推loadingJson('example.com/2.json') - 哪怕2.json的请求网络更快、先返回,
resultList[0]依然对应1.json的响应结果,resultList[1]依然对应2.json的结果
这是$q.all(包括ES6原生Promise.all)的核心特性之一:它会等待所有Promise完成,然后严格按照输入数组的顺序把结果组装成新数组返回,不管每个Promise的resolve顺序如何。所以你完全不用担心顺序错乱的问题。
二、Promises(Angular $http)如何解决跨域问题?
你遇到的是典型的CORS跨域错误,本质是浏览器的同源策略限制,和用不用Promise无关。针对Angular的场景,有几种实用解决方案:
1. 使用JSONP(和jQuery思路一致)
Angular的$http提供了jsonp方法,需要注意两点:
- 目标服务器必须支持JSONP(即能识别并处理回调参数,返回包裹后的代码)
- 请求URL末尾必须加上
?callback=JSON_CALLBACK(Angular会自动替换成实际的回调函数名)
修改你的loadingJson函数示例:
var loadingJson = function(url){ var defer = $q.defer(); // 改用$http.jsonp,注意URL要带callback参数 $http.jsonp(url + '?callback=JSON_CALLBACK').then(function(results){ defer.resolve(results); }, function(err){ defer.reject(err); }); return defer.promise; }; // 调用时传入的URL不用额外带callback promises.push(loadingJson('example.com/1.json')); promises.push(loadingJson('example.com/2.json'));
2. 配置服务器开启CORS(推荐方案)
如果能控制目标服务器的配置,直接在服务器端设置Access-Control-Allow-Origin响应头,允许你的前端域名访问。这种方式比JSONP更灵活,支持POST/PUT等所有HTTP方法,也不需要修改前端请求逻辑。
比如在Nginx中添加配置:
add_header Access-Control-Allow-Origin "https://your-frontend-domain.com"; add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
3. 开发环境使用代理转发
如果是本地开发阶段,可以通过Angular CLI的代理配置转发请求,绕过浏览器的同源限制。比如创建proxy.conf.json文件:
{ "/api": { "target": "http://example.com", "secure": false, "changeOrigin": true } }
启动项目时指定代理文件:ng serve --proxy-config proxy.conf.json,前端请求就改成/api/1.json即可。
附:你的原始代码(格式化后)
var promises = []; var loadingJson = function(url){ var defer = $q.defer(); $http.get(url).then(function(results){ defer.resolve(results); }, function(err){ defer.reject(err); }); return defer.promise; }; promises.push(loadingJson('example.com/1.json')); promises.push(loadingJson('example.com/2.json')); $q.all(promises).then(function(resultList){ // Your handling here, resultList contains the results of both API calls. }, function(errList){ // Your error handling here. });
内容的提问来源于stack exchange,提问作者user21
相关产品推荐
相关产品推荐

