代码之家  ›  专栏  ›  技术社区  ›  Cho Lin Tsai

使用多个iframe VID的ReactJS仅1个可用,其他正在等待承诺

  •  1
  • Cho Lin Tsai  · 技术社区  · 6 年前

    问题已修复,代码已更新

    将youtubeReady Promise放入另一个文件(youtubeReady.js)并从中导入:

    const YTReady = new Promise( (resolve) => {
      window.onYouTubeIframeAPIReady = () => resolve(window.YT);
    });
    
    export default YTReady;
    

    代码已更新标记的文件


    帖子更新:

    根据HMR的回答,我尝试了潜在的解决方案。

    但它不起作用。。。

    (以下代码也已更新)

    I替换原始代码:

    this.player = new Promise (...)
    this.player.then(...)
    

    采用新方法

    const youtubeReady = new Promise(...)
    youtubeReady.then(...)
    

    结果是视频甚至没有显示在firstCmp或secondCmp类obj(构造函数)中。

    我用的是控制台。将(此)记录在这两个组件的componentDidMount()中,未加载视频。

    我做得对吗?还是我错过了什么?


    原始帖子内容

    最近几天,我解决了之前的问题,通过mouseOver/mouseLeave事件让Youtube api正常工作。

    现在我遇到了一个新问题,我正在努力解决两天。

    我有3个组件。

    首先设置脚本标记以获取api(app.js):

    import React, {Component} from "react";
    import ReactDom from "react-dom";
    import './app.scss';
    
    import FirstCmp from './firstCmp.js'
    import secondCmp from './secondCmp.js'
    
    class App extends Component {
    
      componentDidMount() {
        let tag = document.createElement('script');
            tag.src = 'https://www.youtube.com/iframe_api';
        let firstScriptTag = document.getElementsByTagName('script')[0];
            firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
      }
    
      render() {
        return (
            <div id="app">
              <FirstCmp />
              <SecondCmp />
            </div>
        )
      }
    }
    
    ReactDom.render(<App/>, document.getElementById('root'))
    

    然后创建视频(firstCmp.js):

    import React, { Component } from 'react';
    import style from './firstCmp.scss';
    import YTReady from './resource/youtubeReady';
    
    export default class FirstCmp extends Component {
    
      constructor(props) {
    
        super(props);
        // just for example, not real code
        this.state = {
          iframeId: "myIframe",
          src: "src"
        }
    
      }
    
       componentDidMount() {
    
         let youtubeReady = YTReady;
    
         youtubeReady.then( (YT) => {
           this.player = new YT.Player(this.state.iframeId, {
              events: {
                'onReady': () => this.onPlayerReady(),
                'onStateChange': () => this.onPlayerStateChange()
              }
           })
         })
       }
    
    
       mouseOver() {
    
          this.player.playVideo();
    
       }
    
       mouseLeave() {
    
          this.player.pauseVideo();
    
       }
    
       render() {
    
         return (
          <section className={style.firstCmpContent}>
    
            <iframe
              id={this.state.iframeId}
              src={`${this.state.src}`}
              frameBorder="0"
              style={style.firstCmp}
              onMouseOver={ () => this.mouseOver() }
              onMouseLeave={ () => this.mouseLeave() } >
            </iframe>
    
          </section>
        );
       }
    }
    

    到目前为止还不错。第一段视频效果很好。 直到我创建第二个视频。。。(secondCmp.js)

    import React, { Component } from "react";
    import style from './secondCmp.scss';
    import YTReady from './resource/youtubeReady';
    
    
    export default class SecondCmp extends Component {
        constructor(props) {
    
            super(props);
            // just for example, not real code
            this.state = {
              iframeId: "myIframe",
              src: "src"
            }
    
        }
    
        componentDidMount() {
    
          let youtubeReady = YTReady;
    
          youtubeReady.then( (YT) => {
            this.player = new YT.Player(iframeId, {
               events: {
                  'onReady': () => this.onPlayerReady(),
                  'onStateChange': () => this.onPlayerStateChange()
               }
            })
          })
        }
    
    
       mouseOver() {
    
          this.player.playVideo();
    
       }
    
       mouseLeave() {
    
          this.player.pauseVideo();
    
       }
    
       render() {
    
         return (
          <section className={style.secondCmpContent}>
    
            <iframe
              id={this.state.iframeId}
              src={`${this.state.src}`}
              frameBorder="0"
              style={style.secondCmp}
              onMouseOver={ () => this.mouseOver() }
              onMouseLeave={ () => this.mouseLeave() } >
            </iframe>
    
          </section>
        );
       }
    }
    

    现在,只有第二个视频工作,第一个得到了悬而未决的承诺!

    如果我创建了第三个视频,那么第二个和第一个视频将得到待定的承诺 只有新的一个(第三个)在工作,以此类推。

    如何解决此问题?

    1 回复  |  直到 6 年前
        1
  •  1
  •   HMR    6 年前

    创建全球承诺,因为 onYouTubeIframeAPIReady 在加载脚本时调用,并且只应发生一次,此后每次都将准备就绪 you can find a similar question here 。当前您正在覆盖 onYouTubeIframeAPIReady 每次都有不同的功能。

    因此,您可以有一个承诺或服务(而不是每个组件都有一个承诺或服务):

      const youtubeReady = new Promise( (resolve) => {
        window.onYouTubeIframeAPIReady = () => resolve(window.YT);
      });
    

    然后在组件中:

      youtubeReady.then( (YT) => {
        this.player = new YT.Player(iframeId, {//not sure where iframeId comes from
           events: {
              'onReady': () => this.onPlayerReady(),
              'onStateChange': () => this.onPlayerStateChange()
           }
        })
      })