Javascript 使用TS中的Promise从其onload函数获取图像宽度失败

Javascript 使用TS中的Promise从其onload函数获取图像宽度失败,javascript,reactjs,ecmascript-6,promise,Javascript,Reactjs,Ecmascript 6,Promise,我使用以下代码: import React, { Component } from 'react'; import { render } from 'react-dom'; const imageString = 'https://glebekitchen.com/wp-content/uploads/2018/09/neapolitanpepperoni.jpg'; function getPromise(imageData) { return new Promise((r

我使用以下代码:

import React, { Component } from 'react';
import { render } from 'react-dom';

  const imageString = 'https://glebekitchen.com/wp-content/uploads/2018/09/neapolitanpepperoni.jpg';

  function getPromise(imageData) {
    return new Promise((resolve, reject) => {
        const myImage = new Image();
        myImage.onload = () => resolve(myImage.width);
        myImage.onerror = reject(-1);
        myImage.src = imageData; 
      });
  }

  async function getWidth() {
    const promise = await getPromise(imageString);
    promise.then(width => {
        return width;
      }).catch(ex => {
            return -1;
      });
  }
  
class App extends Component<AppProps, AppState> { 
  render() {
    const a = getWidth(); 
    debugger;
    return (
      <div>
        <p>
          {a};
        </p>
      </div>
    );
  }
}

render(<App />, document.getElementById('root'));
import React,{Component}来自'React';
从'react dom'导入{render};
常量imageString=https://glebekitchen.com/wp-content/uploads/2018/09/neapolitanpepperoni.jpg';
函数getPromise(imageData){
返回新承诺((解决、拒绝)=>{
const myImage=新图像();
myImage.onload=()=>resolve(myImage.width);
myImage.onerror=拒绝(-1);
myImage.src=图像数据;
});
}
异步函数getWidth(){
const promise=wait getPromise(imageString);
承诺。然后(宽度=>{
返回宽度;
}).catch(ex=>{
返回-1;
});
}
类应用程序(扩展组件)

虽然希望使用getWidth函数获得宽度,但我只获得宽度作为PromiserResult的承诺 我做错了什么?使用上述承诺时,我如何获得特定值而不是对象


提前感谢

承诺是异步的,因此您必须“等待”它们。有两种方法

  • 使用异步渲染函数等待结果
  • 等待承诺,将变量设置为state,然后让React重新呈现组件
  • 使用异步渲染函数

    class App extends Component<AppProps, AppState> { 
      async render() {
        const a = await getWidth(); 
        debugger;
        return (
          <div>
            <p>
              {a};
            </p>
          </div>
        );
      }
    }
    
    类应用程序扩展组件{
    异步呈现(){
    常数a=等待getWidth();
    调试器;
    返回(
    
    {a} );
    

    ); } }
    使用状态。小心,这是不利的

    class App extends Component<AppProps, AppState> { 
      
      render() {
        const [a, setA] = useState(null);
        getWidth().then(width => setA(width)); 
        debugger;
        return (
          <div>
            <p>
              {a};
            </p>
          </div>
        );
      }
    }
    
    类应用程序扩展组件{
    render(){
    const[a,setA]=useState(null);
    getWidth()。然后(width=>setA(width));
    调试器;
    返回(
    
    {a} );
    

    ); } }
    使用此状态方法的“缺点”是,第一次呈现组件时,组件使用
    null
    作为
    a
    的值。
    最好的一点是,即使异步方法的值还不存在,应用程序也会呈现。您可以添加一些
    加载
    功能,或者
    返回null
    告诉React您根本不想渲染此组件。

    getWidth
    有问题。您正在等待来自
    getPromise
    的结果。这意味着该函数的结果不再是承诺,而是在resolve语句中返回的值。因此,
    then
    catch
    方法将不起作用。相反,只需从
    getPromise

    async function getWidth() {
      return getPromise(imageString);
    }
    
    不要在
    render
    方法中使用副作用操作。这个方法应该做一件事,使用可用的数据来呈现HTML,但不做任何计算或从异步函数获取数据

    为此,您可以使用
    componentDidMount
    生命周期方法,该方法在组件第一次呈现时运行

    在这个方法中,调用
    getWidth
    函数并从中获取图像的宽度。从这里,您应该更新一个状态,该状态将让组件知道其数据已更改,并且应该重新提交组件

    class App extends Component<AppProps, AppState> {
      constructor(props) {
        super(props);
    
        this.state = {
          imageWidth: null // Set a initial state of null.
        }
      }
    
      componentDidMount() {
        getWidth().then(width => {
          this.setState({
            imageWidth: width
          });
        });
      }
    
      render() {
        const imageWidth = this.state.imageWidth;
        
        // If the width is not yet set, render nothing.
        if (imageWidth === null) {
          return null;
        }
    
        return (
          <div>
            <p>
              {a};
            </p>
          </div>
        );
      }
    }
    
    类应用程序扩展组件{
    建造师(道具){
    超级(道具);
    此.state={
    imageWidth:null//将初始状态设置为null。
    }
    }
    componentDidMount(){
    getWidth()。然后(宽度=>{
    这是我的国家({
    图像宽度:宽度
    });
    });
    }
    render(){
    const imageWidth=this.state.imageWidth;
    //如果尚未设置宽度,则不渲染任何内容。
    如果(imageWidth==null){
    返回null;
    }
    返回(
    
    {a} );
    

    ); } }
    您的代码中有很多错误。在
    getWidth
    函数中查看此
    try catch
    块是不必要的;错误处理代码应位于调用代码中。更不用说从
    catch
    块返回错误将隐式地将承诺拒绝转换为承诺履行,从而在调用代码中调用履行处理程序。您可以在一行中重新编写
    getWidth
    函数:
    返回getPromise(imageString)@Yousaf,我不确定情况是否如此。谢谢你澄清这一点。修改了答案。如果您对更多详细信息感兴趣,请参阅: