JavaScript 检查资源是否可以通过获取访问
JavaScript checking if resource is reachable with fetch
我基本上只是想验证是否可以从正在执行的客户端访问资源。我不能使用 XHR
,因为目标资源不允许这样做。
我是 JS 的新手,目前正在使用它 (executable here):
var done = false;
var i = 1;
var t = "https://i.stack.imgur.com/Ya15i.jpg";
while(!done && i < 4)
{
console.log("try "+i);
done = chk(t);
sleep(1000);
i = i+1;
if (done)
{
console.log("Reachable!");
break;
}
else
{
console.log("Unreachable.");
}
}
function chk(target)
{
console.log("checking "+target)
fetch(target, {mode: 'no-cors'}).then(r=>{
return true;
})
.catch(e=>{
return false;
});
}
// busy fake sleep
function sleep(s)
{
var now = new Date().getTime();
while(new Date().getTime() < now + s){ /* busy sleep */ }
}
我原以为这段代码会检查资源,打印结果,然后等待一秒钟。重复此操作,直到 3 次尝试不成功或其中一次成功。
相反,执行会阻塞一段时间,然后立即打印所有 console.logs
并且资源永远无法访问(它是)。
我知道 fetch
操作是异步的,但我认为如果我之前声明 done
并实现睡眠,它应该可以工作。在最坏的情况下,while 循环将使用先前声明的 done
.
如何实现所描述的行为?欢迎任何建议。
试试这个,希望它有效
var myHeaders = new Headers();
myHeaders.append('Content-Type', 'image/jpeg');
var myInit = { method: 'GET',
headers: myHeaders,
mode: 'no-cors',
cache: 'default' };
var myRequest = new Request('https://i.stack.imgur.com/Ya15i.jpg');
fetch(myRequest,myInit).then(function(response) {
...
});
您的 chk 函数 return 未定义,您 return true/false 来自 promise 回调而不是来自容器函数。
你应该在 catch 回调中使用递归和超时。
它将是这样的:
var i = 0;
var done = false;
var t = "https://i.stack.imgur.com/Ya15i.jpg";
(function chk(target){
console.log("checking "+target)
fetch(target, {mode: 'no-cors'}).then(r=>{
done = true;
console.log("Reachable!");
})
.catch(e=>{
console.log("Unreachable.");
if(i<4){
setTimeout(function(){
chk(target)
},1000)
}
});
})(t)
您不能 return 在回调中。当您这样做时,returning 是回调,而不是父函数。事实上,函数 chk
永远不会 returning 任何东西。
听起来您打算做的是 return 由 fetch return 承诺。并尝试获取三次。
试试这个:
const numberOfTries =3;
currentTry = 1;
var t = "https://i.stack.imgur.com/Ya15i.jpg";
chk(t);
function tryCheck(resource, currentTry) {
chk(resource).done(function(){
console.log("Reachable!");
}).catch(function(e) {
console.log("Unreachable.");
if (currentTry >= numberOfTries) return;
sleep(1000);
tryCheck(resource, currentTry + 1);
});
}
function chk(resource) {
console.log("checking "+target);
return fetch(target, {mode: 'no-cors'});
}
主要问题是您正试图 return 从回调中。这是没有意义的。
但是 fetch
是基于 Promise 的请求,您也可以使用 Promise 来模拟延迟
像这样应该可以解决问题
// promise based delay
const delay = timeout => new Promise(resolve => setTimeout(resolve, timeout))
// check if target can be fetched
const check = target => fetch(target, {...})
.then(response => response.ok)
const ping = (target, times = 3, timeout = 1000) => check(target)
.then(found => {
if(!found && times) { // still can check
// wait then ping one more time
return delay(timeout).then(() => ping(target, times - 1, timeout))
}
return found
})
ping('https://i.stack.imgur.com/Ya15i.jpg')
.then(found => {
console.log(found ? 'Reachable': 'Unreachable')
})
你的 sleep
函数正在阻塞,你真正想要的是一个递归函数,returns 在检查 url n
次后延迟 returns 的承诺 y
秒等等
像这样
function chk(target, times, delay) {
return new Promise((res, rej) => { // return a promise
(function rec(i) { // recursive IIFE
fetch(target, {mode: 'no-cors'}).then((r) => { // fetch the resourse
res(r); // resolve promise if success
}).catch( err => {
if (times === 0) // if number of tries reached
return rej(err); // don't try again
setTimeout(() => rec(--times), delay ) // otherwise, wait and try
}); // again until no more tries
})(times);
});
}
这样使用
var t = "https://i.stack.imgur.com/Ya15i.jpg";
chk(t, 3, 1000).then( image => {
console.log('success')
}).catch( err => {
console.log('error')
});
请注意,这不会在 404 或 500 上失败,任何响应都是成功的请求。
我基本上只是想验证是否可以从正在执行的客户端访问资源。我不能使用 XHR
,因为目标资源不允许这样做。
我是 JS 的新手,目前正在使用它 (executable here):
var done = false;
var i = 1;
var t = "https://i.stack.imgur.com/Ya15i.jpg";
while(!done && i < 4)
{
console.log("try "+i);
done = chk(t);
sleep(1000);
i = i+1;
if (done)
{
console.log("Reachable!");
break;
}
else
{
console.log("Unreachable.");
}
}
function chk(target)
{
console.log("checking "+target)
fetch(target, {mode: 'no-cors'}).then(r=>{
return true;
})
.catch(e=>{
return false;
});
}
// busy fake sleep
function sleep(s)
{
var now = new Date().getTime();
while(new Date().getTime() < now + s){ /* busy sleep */ }
}
我原以为这段代码会检查资源,打印结果,然后等待一秒钟。重复此操作,直到 3 次尝试不成功或其中一次成功。
相反,执行会阻塞一段时间,然后立即打印所有 console.logs
并且资源永远无法访问(它是)。
我知道 fetch
操作是异步的,但我认为如果我之前声明 done
并实现睡眠,它应该可以工作。在最坏的情况下,while 循环将使用先前声明的 done
.
如何实现所描述的行为?欢迎任何建议。
试试这个,希望它有效
var myHeaders = new Headers();
myHeaders.append('Content-Type', 'image/jpeg');
var myInit = { method: 'GET',
headers: myHeaders,
mode: 'no-cors',
cache: 'default' };
var myRequest = new Request('https://i.stack.imgur.com/Ya15i.jpg');
fetch(myRequest,myInit).then(function(response) {
...
});
您的 chk 函数 return 未定义,您 return true/false 来自 promise 回调而不是来自容器函数。
你应该在 catch 回调中使用递归和超时。 它将是这样的:
var i = 0;
var done = false;
var t = "https://i.stack.imgur.com/Ya15i.jpg";
(function chk(target){
console.log("checking "+target)
fetch(target, {mode: 'no-cors'}).then(r=>{
done = true;
console.log("Reachable!");
})
.catch(e=>{
console.log("Unreachable.");
if(i<4){
setTimeout(function(){
chk(target)
},1000)
}
});
})(t)
您不能 return 在回调中。当您这样做时,returning 是回调,而不是父函数。事实上,函数 chk
永远不会 returning 任何东西。
听起来您打算做的是 return 由 fetch return 承诺。并尝试获取三次。
试试这个:
const numberOfTries =3;
currentTry = 1;
var t = "https://i.stack.imgur.com/Ya15i.jpg";
chk(t);
function tryCheck(resource, currentTry) {
chk(resource).done(function(){
console.log("Reachable!");
}).catch(function(e) {
console.log("Unreachable.");
if (currentTry >= numberOfTries) return;
sleep(1000);
tryCheck(resource, currentTry + 1);
});
}
function chk(resource) {
console.log("checking "+target);
return fetch(target, {mode: 'no-cors'});
}
主要问题是您正试图 return 从回调中。这是没有意义的。
但是 fetch
是基于 Promise 的请求,您也可以使用 Promise 来模拟延迟
像这样应该可以解决问题
// promise based delay
const delay = timeout => new Promise(resolve => setTimeout(resolve, timeout))
// check if target can be fetched
const check = target => fetch(target, {...})
.then(response => response.ok)
const ping = (target, times = 3, timeout = 1000) => check(target)
.then(found => {
if(!found && times) { // still can check
// wait then ping one more time
return delay(timeout).then(() => ping(target, times - 1, timeout))
}
return found
})
ping('https://i.stack.imgur.com/Ya15i.jpg')
.then(found => {
console.log(found ? 'Reachable': 'Unreachable')
})
你的 sleep
函数正在阻塞,你真正想要的是一个递归函数,returns 在检查 url n
次后延迟 returns 的承诺 y
秒等等
像这样
function chk(target, times, delay) {
return new Promise((res, rej) => { // return a promise
(function rec(i) { // recursive IIFE
fetch(target, {mode: 'no-cors'}).then((r) => { // fetch the resourse
res(r); // resolve promise if success
}).catch( err => {
if (times === 0) // if number of tries reached
return rej(err); // don't try again
setTimeout(() => rec(--times), delay ) // otherwise, wait and try
}); // again until no more tries
})(times);
});
}
这样使用
var t = "https://i.stack.imgur.com/Ya15i.jpg";
chk(t, 3, 1000).then( image => {
console.log('success')
}).catch( err => {
console.log('error')
});
请注意,这不会在 404 或 500 上失败,任何响应都是成功的请求。