我遇到了这段代码的问题:
// var env_array = ["env1", "env2", "env3", "env4"];
Promise.all(env_array.map(function(env) {
return device_get_env(env).catch(function(err) { return err });
})).then(function(data) {
console.log(data);
data.forEach(function(entry) {
console.log(entry.data.connected);
});
}).catch(function(data) {
console.log(data);
});
function device_get_env(env) {
var env = ...;
var device_id = ...;
return get_token_data(env, 0).then(function(data) {
var url_base = ... ;
return $.ajax({
url: url_base,
method: "GET",
dataType: 'json',
headers: {Authorization: data.token_type + " " + data.access_token}
});
});
}
function get_token_data(env, auth) {
var client_id = env_tokens[env].client_id;
var client_secret = env_tokens[env].client_secret;
var audience = auth == 1 ? "https://" + env + ".xxxx.com/api/v2/" : "yyyy.com";
return $.ajax({
url: "https://" + env + ".xxxx.com/oauth/token",
method: "POST",
data: {
"client_id": client_id,
"client_secret": client_secret,
"audience": audience,
"grant_type": "client_credentials"
},
dataType: 'json'
});
}
基本上我需要迭代env_array
并在我的某些环境中查找设备项。
device_get_env()返回AJAX调用,可能是成功/ 200或错误/ 404。
因此,除非所有承诺都得到解决,否则我的Promises.all将不会返回。
我一直在挖掘如何克服这一点。
尝试实施此解决方案:https://stackoverflow.com/a/30378082/1913289,但我在此处遇到此错误:
TypeError: device_get_env(env).catch is not a function. (In 'device_get_env(env).catch(function(err) {return err} )', 'device_get_env(env).catch' is undefined)
用这里的代码解决这个问题的方法是什么?
@Bergi 建议的UPD:实施
function get_token_data(env, auth) {
var client_id = env_tokens[env].client_id;
var client_secret = env_tokens[env].client_secret;
var audience = auth == 1 ? "https://" + env + ".xxxx.com/api/v2/" : "yyyy.com";
return Promise.resolve(
$.ajax({
url: "https://" + env + ".xxxx.com/oauth/token",
method: "POST",
data: {
"client_id": client_id,
"client_secret": client_secret,
"audience": audience,
"grant_type": "client_credentials"
},
dataType: 'json'
})
)
}
function device_get_env(env) {
var env = ...;
var device_id = ...;
return get_token_data(env, 0).then(function(data) {
var url_base = ... ;
return Promise.resolve(
$.ajax({
url: url_base,
method: "GET",
dataType: 'json',
headers: { Authorization: data.token_type + " " + data.access_token }
})
)
});
}
Promise.all(env_array.map(function(env) {
return device_get_env(env).then(null, function(err) { return err });
})).then(function(data) {
console.log(data);
}).catch(function(data) {
console.log(data);
});
UPD1:
Promise.all(env_array.map(function(env) {
return device_get_env(env).catch(function(err) {return err} );
})).then(function(data) {
console.log(data);
}).catch(function(data) {
console.log(data);
});
最终更新: 我使用了fetch:https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#Supplying_request_options
替换我的AJAX http请求。
fetch()返回的Promise不会拒绝HTTP错误状态,即使>如果响应是HTTP 404或500.相反,它将正常解析> (将ok状态设置为false),它只会拒绝网络故障>或者如果有任何事情妨碍了请求的完成。
Promise.all示例:
Promise.all(env_array.map(function(env) {
return device_get_env(env);
})).then(function(data) {
console.log(data);
}).catch(function(data) {
console.log(data);
});
获取示例:
function get_token_data(env, auth) {
var client_id = env_tokens[tenant].client_id;
var client_secret = env_tokens[env].client_secret;
var audience = auth == 1 ? "https://" + env + ".xxxx.com/api/v2/" : "yyyy.com";
var url_base = "https://" + env + ".xxxx.com/oauth/token";
var myInit = {
method: 'POST',
mode: 'cors',
dataType: 'json',
cache: 'default',
data: {
"client_id": client_id,
"client_secret": client_secret,
"audience": audience,
"grant_type": "client_credentials"
}
};
return fetch(url_base, myInit);
}
答案 0 :(得分:3)
您的问题是device_get_env(env)
返回jQuery承诺,而不是ES6承诺。那些don't have a .catch()
method until v3.0 ......
要解决此问题,您可以
return Promise.resolve($.ajax(…))
或中执行get_token_data
.then(null, function(err) { return err })
代替.catch(…)
答案 1 :(得分:2)
您的第一个线索是您没有在代码中的某处返回Promise,这是您的错误:
TypeError: device_get_env(env).catch is not a function.
错误告诉您正在尝试在没有.catch()
方法的对象上调用catch()
(即使AJAX对象在技术上“可以”,早期版本的jQuery没有catch()
方法。所以一个解决方案就是升级你的jQuery 1 版本。
您的特殊问题是您没有从get_token_data()
函数中获得您期望的AJA Promise,而是返回jQuery Promise。
因此,如果您通过catch()
中的Promise.resolve()
将jQuery承诺包装/投射到get_token_data()
能够的ES6承诺,那么您应该走在正确的轨道上:
function get_token_data(env, auth) {
var client_id = env_tokens[env].client_id;
var client_secret = env_tokens[env].client_secret;
var audience = auth == 1 ? "https://" + env + ".xxxx.com/api/v2/" : "yyyy.com";
var ajaxOptions = {
url: "https://" + env + ".xxxx.com/oauth/token",
method: "POST",
dataType: 'json',
data: {
"client_id": client_id,
"client_secret": client_secret,
"audience": audience,
"grant_type": "client_credentials"
}
};
// here is where the magic happens to cast your
// jQuery Promise into a 'catchable' Promise
return Promise.resolve($.ajax(ajaxOptions));
};
我无法测试此代码,因此您可能需要对其进行调整,但这是基本的想法。
希望这有帮助!
1 感谢@Bergi reminding me of this。