简体   繁体   English

promise 解决但代码不继续

[英]The promise resolves but the code doesn't proceed

The Codepen has been added (I have commented the if block (where the issue exist) to show you the correct behavior of the function and You need to click on somewhere to play the audio of the video): Codepen 已添加(我已评论 if 块(存在问题)以向您展示 function 的正确行为,您需要单击某处播放视频的音频):

https://codepen.io/pixy-dixy/pen/mdOVgZw https://codepen.io/pixy-dixy/pen/mdOVgZw

I have a wired issue with my function.我的 function 存在有线问题。 you don't need to read and understand every part of the function although I've copied all the functions for you to have a look.您不需要阅读和理解 function 的每个部分,尽管我已经复制了所有功能供您查看。 The MovieAudio function has PlayAudio() function inside and it's where the issue exist... MovieAudio function 内部有PlayAudio() function,这就是问题所在...

We have this line of code inside PlayAudio() function:我们在PlayAudio() function 中有这行代码:

console.log('before sfx');
if(sfx) { await sfxPlay(sfx.before_listen); } 
console.log('after sfx');

As you see we have two console logs right before and after this line.如您所见,我们在此行之前和之后有两个控制台日志。 If sfxPlay promise resolves we should see the console.log('after sfx');如果sfxPlay promise 解决了,我们应该看到console.log('after sfx'); but we never see this unfortunatly!!!但不幸的是,我们从来没有看到过这个!

I have tested the await sfxPlay(sfx.before_listen);我已经测试了await sfxPlay(sfx.before_listen); another place outside of this code and it works correctly!!!!此代码之外的另一个地方,它工作正常!!!!

In the first sight I thought maybe sfxPlay function doesn't resolve correctly so I put console.log('sfx has been resolved');乍一看,我想也许sfxPlay function 没有正确解析,所以我把console.log('sfx has been resolved'); inside sfxPlay function to check if sfxPlay function is resolved correctly, and yes it resolves correctly but still we don't proceed to console.log('after sfx');sfxPlay function 内部检查sfxPlay function 是否正确解析,是的,它正确解析,但我们仍然没有继续执行console.log('after sfx');

Here is my console.这是我的控制台。 note that we don't see console.log('after sfx');请注意,我们看不到console.log('after sfx'); which we except to see of course:我们当然不会看到:

在此处输入图像描述

Why?为什么? What I'm missing?我错过了什么? it seems simple but it doesn't behave correctly?!它看起来很简单,但它的行为不正确?!

Please Help... Ant comments or any guess is greatly appreciated...请帮助... Ant 评论或任何猜测非常感谢...

let StopMovieAudio;

function MovieAudio(duration, stress, option = {}) {

    let movieAudioResolve;
    const speed = option.speed ? option.speed : 1;
    const sfx = option.sfx ? false : true;
    const guideIndex =  option.guideIndex ? [...Array(option.guideIndex).keys()] : []; 
    if(!stress) stress = { to: '__', from: '__', within: ['__-__'] };
    const guide = !!guideIndex.length;
    const video = document.createElement('video');
    document.body.appendChild(video);
    video.id = 'audio-clip'; 
    const clip = document.getElementById("audio-clip");
    clip.style.visibility = "hidden";
    const source = document.createElement('source');
    source.src = getBlob(clipSource);
    source.type = 'video/mp4';
    video.appendChild(source);
    video.load();
    const start = duration.start + startPlus;
    const end = duration.end + endPlus;

    PlayAudio();
    
    async function PlayAudio() {
        clip.currentTime = start;
        clip.playbackRate = speed;
        console.log('sfx', sfx);
        console.log('before sfx');
        if(sfx) { await sfxPlay(sfx.before_listen); } // sfx is true and we enter the if block
        console.log('after sfx');
        StartAudio();
        const endCheck = setInterval(endCheckInterval, 5);
        function endCheckInterval() {
            guidePhraseUpper(guideIndex[0]);
            checkStopMovie();
        }
    } // end of Play function

    function checkStopMovie() {
        if (clip.currentTime >= end) {
            clearInterval(endCheck);
            StopMovieAudio();
            guidePhrasesDown();
        }
    }

    function guidePhraseUpper(index) {
        if(!guideIndex.length) return;
        if (clip.currentTime >= portionDurations[index].start) {
            guideIndex.shift();
            guidePhrasesDown();
            guidePhraseUp(movieSentenceArrayEn[index]);
        }
    }

    function guidePhrasesDown() {
        if(!guide) return;
        const component = $(`iframe[src*='${components.chief}']`)[0];
        referenceString.split(' ').forEach((phrase, index) => component.contentWindow.guideWordDown(index));
    }

    function StartAudio() {
        console.log('start of StartAudio');
        clip.volume = 1;
        clip.play();
        stressEffectTo();
        stressEffectFrom();
        stressEffectWithin();
    } 

    StopMovieAudio = () => {
        const audioClip = document.getElementById("audio-clip");
        if(audioClip) { document.body.removeChild(audioClip); }
        if(typeof StopMovieAudio === "function") { movieAudioResolve(); }
    } 

    function stressEffectTo() {
        if(stress.to.includes('_')) { return; }
        clip.playbackRate = 0.75;
        speedUpFrom(stress.to);
    }

    function stressEffectFrom() {
        if(stress.from.includes('_')) { return; }
        clip.playbackRate = 1;
        speedDownFrom(stress.from);
    }

    function stressEffectWithin() {
        const stressWithin = stress.within.filter(w => !w.includes('_'));
        if(!stressWithin.length){ return; }
        for(let i = 0; i < stressWithin.length; i++) {
            speedDownFrom(stressWithin[i].split('-')[0]);
            speedUpFrom(stressWithin[i].split('-')[1]);
        }
    } // end of stressEffectWithin function

    function speedUpFrom(timer) {
        const endCheck = setInterval(endCheckInterval, 5);
        function endCheckInterval() {
            if (clip.currentTime >= timer) {
                clearInterval(endCheck);
                clip.playbackRate = 1;
            }
        }
    } // end of Track function

    function speedDownFrom(timer) {
        const endCheck = setInterval(endCheckInterval, 5);
        function endCheckInterval() {
            if (clip.currentTime >= timer) {
                clearInterval(endCheck);
                clip.playbackRate = 0.7;
            }
        }
    } // end of Track function

    return new Promise(resolve => { 
        movieAudioResolve = resolve;
        console.log('Promise reached');
    });

} // end of MovieAudio function

let sfxPlayResolve;

function sfxPlay(source) {
    return new Promise(resolve => { 
        sfxPlayResolve = resolve;
        const sfxAudio = new Audio(source);
        playingAudios.push(sfxAudio);
        sfxAudio.play();
        sfxAudio.onerror = function() {
            console.log("Error loading: " + this.src);
            sfxPlay(sfx.no_sources);
            resolve(); 
        }
        sfxAudio.addEventListener("ended", function() {  
            sfxAudio.currentTime = 0;          
            resolve();    
            console.log('sfx has been resolved');    
        }); 
    });
}

try calling the play function like this:尝试像这样调用播放 function :

let flag = true;
    sfxAudio.addEventListener("canplay", function() {  
        console.log('sfx can play');
        flag && this.play();
        flag = false;
    });

I think it is a race condition, that would also explain why your code fails locally, but works in the codepen.我认为这是一个竞争条件,这也可以解释为什么您的代码在本地失败,但在 codepen 中有效。

The docs also recommend an Event-based approach to calling play(): https://developer.mozilla.org/en-US/docs/Web/API/HTMLAudioElement/Audio文档还建议使用基于事件的方法来调用 play(): https://developer.mozilla.org/en-US/docs/Web/API/HTMLAudioElement/Audio

The user has to interact with the document, one cannot just autoplay a video.用户必须与文档进行交互,不能只是自动播放视频。 See https://developers.google.com/web/updates/2017/09/autoplay-policy-changes请参阅https://developers.google.com/web/updates/2017/09/autoplay-policy-changes

For me it works just fine when the PlayAudio function is run on clicking a button, like:对我来说,当PlayAudio function 在单击按钮时运行时,它工作得很好,例如:

HTML: HTML:

<button onclick="startTheShow()">Play</button>

JS: JS:

// setTimeout(async () => {
//   await MovieAudio({start: '3', end: '15'}, { to: '__', from: '__', within: ['__-__'] }, 1, true); 
// }, 5000);

const startTheShow = async () => {
  await MovieAudio({start: '3', end: '15'}, { to: '__', from: '__', within: ['__-__'] }, 1, true); 
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM