使用Promise进行onload和onerror后返回状态值

问题描述

我正在尝试查看使用javascript onload和onerror是否成功加载页面/ img。我试图读取状态变量,但是当我分配变量以读取状态时却无法读取。 我正在尝试使用可能的答案所提供的承诺,但仍然有些困惑。


const validateInput = (input) => {
  const errors = {};
  ... 

    if(!(isimgurlValid(input)))
    {
      errors = `wrong image'` 
    }
    ... 
  return errors;

const isimgurlValid = (path) => {
  let img = document.createElement('img');
  img.src = path;  
  let valid
 const promise = new Promise(resolve => {
    const img = new Image();
    img.onload = () => resolve({path,"status": 'ok'});
    img.onerror = () => resolve({path,"status": 'error'});
     img.src = path;
});
promise.then(function(val) { 
  console.log(val); 
  valid = val.status
}); 
console.log (valid)
}

//when I use async,my render functions no long render the errors properly
export const renderimgurlInput = ({ input,label,type,size,required,Meta: { touched,error } }) => (
  <div className={
    cs('form-group',{
      'has-error': touched && error,'required-input' : required
    })
  }>
    <label className="control-label" htmlFor={input.name}>{label}</label>
    <input {...input} placeholder={required ? 'required' : ''} className="form-control" /> 
    {touched && error &&
      <span className="help-block">{error}</span>
    }
    {touched && !error &&
      <h1 className="help-block">{error} 'Image worked'</h1>
    }
  </div>
)

解决方法

const isImgURLValid = (path) => {
    return new Promise((resolve,reject) => {
        const img = document.createElement("img");
        img.src = path;
        img.onload = resolve;
        img.onerror = reject;
        img.src = path;
        document.body.appendChild(img);
    });
};

isImgURLValid("https://www.gravatar.com/avatar/206601a888686677c4a74c89d9a2920f?s=48&d=identicon&r=PG")
    .then(() => console.log("Path is valid"))
    .catch(() => console.error("Path isn't valid"))

,

我想您可能对Promise有点陌生,表明您已经阅读了建议的副本,但是您可以通过以下方式重新编写代码

const isImgUrlValid = (path) => {
  return new Promise( (resolve,reject) => {
    const img = new Image();
    img.onload = () => resolve({path,"status": 'ok'});
    img.onerror = () => reject({path,"status": 'error'});
     img.src = path;
  });
};

// when it's found,resolve got called and we know it succeeded
isImgUrlValid('https://www.gravatar.com/avatar/153828e74e3fb5f7aeb19a28a78a378a?s=32&d=identicon&r=PG&f=1').then( status => console.log('image found') );

// when it's not found reject was called,and we need to catch it
isImgUrlValid('invalid_uri').then( _ => console.log('I will never be called') ).catch( err => console.log('no image found') );

然后这将使用“解决”(成功)和“拒绝”(失败)以使用诺言如何正常运行的方式。

通过兑现承诺,任何消费者都可以使用thencatch链来成功或失败

假设您要在函数中使用以上代码,那么它会有所变化,您无法真正地进行同步检查,除非调用者是async函数,在这种情况下,您可以这样做:

const validateInput = async () => {
  let isValidImage = false;
  try {
   isValidImage = await isImgUrlValid( path );
  } catch (ex) {
    // not a correct image
    
  }
};

但这不能为您提供任何帮助,因为validateInput隐式返回一个诺言,因此您必须将此诺言作为诺言处理。

,

您应该将您创建的承诺从isImgURlValid返回给呼叫者。然后,调用者可以等待promise解析,并使用解析后的值来查看所提供的图像源是否有效。

这是一个受问题代码启发的示例。您可以在输入框中输入图像源,然后按 Enter 触发事件。

const isImgURlValid = (path) => { 
  return new Promise(resolve => {    
    const img = new Image()
    img.src = path;
    img.onload = () => resolve(true);
    img.onerror = () => resolve(false);
    
    // img starts loading src when added to the DOM
    document.body.append(img);
    document.body.removeChild(img);
  });
};

const validateInput = async (input) => {
  const errors = {};
  if (!await isImgURlValid(input)) {
    errors.url = "invalid";
  }
  return errors;
};

document.getElementById("input").addEventListener("change",({target}) => {
  validateInput(target.value).then(console.log);
});
<input id="input" type="text" />