javascript - 使用多个 iframe vids 的 ReactJS 只有 1 个有效,其他是 Promise pending

标签 javascript reactjs youtube-api es6-promise

问题已修复,代码已更新

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

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

export default YTReady;

代码更新标记文件


帖子更新:

我已经根据 HMR 的回答尝试了可能的解决方案。

但是没用...

(以下代码也已更新)

我替换原来的代码:

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

采用新方法

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

结果是视频甚至没有出现在 firstCmp 和 secondCmp 类对象(构造函数)中。

我在这两个组件的 componentDidMount() 中使用了 console.log(this),但没有加载任何视频。

我做对了吗?或者我错过了什么?


原始帖子内容

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

现在我遇到了一个新问题,我为此苦苦挣扎了 2 天。

我有 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>
    );
   }
}

现在,只有第二个视频有效,第一个视频获得待定 promise !

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

我该如何解决这个问题?

最佳答案

创建一个全局 promise ,因为 onYouTubeIframeAPIReady 在加载脚本时被调用并且应该只发生一次,之后每次都会准备好 you can find a similar question here .目前,您每次都使用不同的函数覆盖 onYouTubeIframeAPIReady

所以你可以有一个 promise 或服务(不是每个组件一个):

  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()
       }
    })
  })

关于javascript - 使用多个 iframe vids 的 ReactJS 只有 1 个有效,其他是 Promise pending,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49749300/

相关文章:

ios - UITableViewCell 中的 YTPlayerView

php - 将文件从实时服务器上传到 youtube 不起作用?

youtube - 更新免费的 youtube 画廊以使用 Youtube 3.0 API

javascript - 在 map 上定位

reactjs - 为什么在 Material-UI Avatar 组件的浏览器中没有显示图像?

reactjs - react hook 如何检测组合键 cmd+enter

javascript - 如何比较数组中不同对象的值

javascript - 向下滚动时词缀元素闪烁

javascript - 统计 LI 的数量,然后将类添加到父 UL

javascript - 如何获取正在运行 React 应用程序的当前域名