将 Promise 用于 onload 和 onerror 后返回状态值

Returning status values after using Promise for onload and onerror

我正在尝试使用 javascript onload 和 onerror 查看 page/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', size, {
      '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"))

我猜你可能对 promises 有点陌生,这表明你已经阅读了建议的副本,但你可以按照以下方式重新制定你的代码

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') );

这将使用 resolve(成功)和 reject(失败)来使用 promise 工作的正常流程。

通过返回承诺,任何消费者都可以使用 thencatch 链来处理成功或失败

假设你想在一个函数中使用上面的代码,然后它改变了一点,你不能真正同步地检查这个,除非调用者是一个 async 函数,在这种情况下你可以这样做喜欢:

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

但这对你没有帮助,因为现在 validateInput 隐含地 returns 一个承诺,所以你必须把这个作为一个承诺来处理。

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

这里是受问题代码启发的例子。您可以在输入框中输入图片来源,然后按回车触发事件。

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" />