72494


新しく質問を立てた方が良いと言われたので[前回の質問](https://ja.stackoverflow.com/questions/72450/javascript%E3%81%A7dom%E5%87%A6%E7%90%86%E3%81%AE%E3%82%BF%E3%82%A4%E3%83%9F%E3%83%B3%E3%82%B0%E3%81%8C%E5%90%88%E3%82%8F%E3%81%9A%E5%80%A4%E3%82%92%E4%B8%8A%E6%89%8B%E3%81%8F%E5%87%A6%E7%90%86%E5%87%BA%E6%9D%A5%E3%81%AA%E3%81%84)の続きになります。  
JavaScriptの[color-thies](https://lokeshdhakar.com/projects/color-
thief/#getting-
started)というライブラリーを使用してプログラムがimgタグの`src`を書き換えたタイミングでライブラリーを実行したいのですが、書き換わる前に処理が実行されてしまうため上手く画像の色を取得出来ません。  
前回の回答者様は画像にloadイベントを持たせると良いと話されていたのですが、いまいち理解出来ていないです。  
`Observer`で書き換えを監視してもタイミングを合わせる事が出来るのではと少し考えています。

[code]

    class callPythonFnc {
        async getTitle(input, dlcard) {
            let title = await eel.get_title(input.value)();
            dlcard.querySelector('.dlcard__title > .dlcard__videoName').innerText = title;
        }
        async getSrc(videoID, thumbnailIMG) {
            let url = await eel.get_src(videoID)();
            thumbnailIMG.src = url;
        }
    
    }
    
    class thumbnail {
        constructor(){
            this.DOM = {}
            this.DOM.inputURL = document.querySelectorAll('.dlcard__url > input');
            this.DOM.dlcardWrap = document.querySelector(".dlcardWrap");
            this._addEvent();
        }
    
        getVideoID(input) {
            if (input.value.match(/^https:\/\/www\.youtube\.com\/watch\?v=.*/)) {
                const url = new URL(input.value)
                //urlの?以降の値を取り出す。
                let pairs = url.search.substring(1).split('&');
                let params = {}
                for(let pair of pairs) {
                    let kv = pair.split('=');
                    //それぞれをpairで辞書型格納する。
                    params[kv[0]] = kv[1];
                }
                let videoID = params.v;
                return videoID;
            }else{
                return false;
            }
        }
    
        changeTitleThumbnail(elm) {
            const input = elm.target;
            if (!input.parentElement.classList.contains("dlcard__url")) {
                console.log('dlcard_urlが取得出来ていないです。')
            }else{
                let videoID = this.getVideoID(input);
                let dlcard = input.closest('.dlcard');
                let thumbnailIMG = dlcard.childNodes[3].childNodes[1];
                if(videoID) {
                    new callPythonFnc().getTitle(input, dlcard)
                    new callPythonFnc().getSrc(videoID, thumbnailIMG);
                }else{
                    input.value = '';
                    input.placeholder = 'URLが違います。';
                }
            }
        }
    
        _addEvent() {
            this.params = {}
            this.DOM.dlcardWrap.addEventListener("blur", this.changeTitleThumbnail.bind(this), true);
        }
    }
    
    new thumbnail();
    
[/code]

## 追記

addEventListnerを使用してコードを書いたのですが、指定した要素をコールバック側で取得するにはどうしたら良いのでしょうか？

[code]

    class callPythonFnc {
        async getTitle(input, dlcard) {
            let title = await eel.get_title(input.value)();
            dlcard.querySelector('.dlcard__title > .dlcard__videoName').innerText = title;
        }
        async getSrc(videoID, thumbnailIMG) {
            let url = await eel.get_src(videoID)();
            thumbnailIMG.src = url;
        }
    
    }
    
    class thumbnail {
        constructor(){
            this.DOM = {}
            this.DOM.inputURL = document.querySelectorAll('.dlcard__url > input');
            this.DOM.dlcardWrap = document.querySelector(".dlcardWrap");
            this._addEvent();
        }
    
        getVideoID(input) {
            if (input.value.match(/^https:\/\/www\.youtube\.com\/watch\?v=.*/)) {
                const url = new URL(input.value)
                //urlの?以降の値を取り出す。
                let pairs = url.search.substring(1).split('&');
                let params = {}
                for(let pair of pairs) {
                    let kv = pair.split('=');
                    //それぞれをpairで辞書型格納する。
                    params[kv[0]] = kv[1];
                }
                let videoID = params.v;
                return videoID;
            }else{
                return false;
            }
        }
    
        imgRGB(thumbnailIMG) {
            console.log(thumbnailIMG);
            const colorThief = new ColorThief();
            const thumColor = colorThief.getColor(thumbnailIMG);
            console.log(thumColor);
        }
    
        changeTitleThumbnail(elm) {
            const input = elm.target;
            if (!input.parentElement.classList.contains("dlcard__url")) {
                console.log('dlcard_urlが取得出来ていないです。')
            }else{
                let videoID = this.getVideoID(input);
                let dlcard = input.closest('.dlcard');
                let thumbnailIMG = dlcard.childNodes[3].childNodes[1];
                thumbnailIMG.addEventListener("load", this.imgRGB, true);
                if(videoID) {
                    new callPythonFnc().getTitle(input, dlcard)
                    new callPythonFnc().getSrc(videoID, thumbnailIMG);
                }else{
                    input.value = '';
                    input.placeholder = 'URLが違います。';
                }
            }
        }
    
        _addEvent() {
            this.params = {}
            this.DOM.dlcardWrap.addEventListener("blur", this.changeTitleThumbnail.bind(this), true);
        }
    }
    
    new thumbnail();
    
[/code]


CC BY-SA 4.0
2020-12-08T01:13:50.567
72490
2020-12-08T14:04:59.687
2020-12-08T08:59:18.537
22565
22565
question
javascript 非同期
JavaScriptで画像がロードされる前にプログラムが走り、上手く処理出来ない。


2通りの方法を紹介します。  
<img>要素が変数 `img`、画像URLが 変数 `imageUrl` だとすると、

  * コールバック内で直接処理する

[code]

    img.addEventListener('load', event => {
      // ロード成功したときの処理。event.target に img が入っている。
    }, {once:true});
    img.addEventListener('error', event => { ロード失敗したときの処理 }, {once:true});
    img.src = imageUrl;
    
[/code]

  * コールバックをPromiseで包んで、`await`する

[code]

    function loadImage(img, imageUrl) {
      return new Promise((resolve, reject) => {
        img.addEventListener('load', resolve, {once:true});
        img.addEventListener('error', reject, {once:true});
        img.src = imageUrl;
       });
    }
    
    async foo() {
     ....
     await loadImage(img, imageUrl);
     ロード成功したときの処理;
    }
    
[/code]


CC BY-SA 4.0
2020-12-08T02:20:59.193
72494
2020-12-08T14:04:59.687
2020-12-08T14:04:59.687
3475
3475
72490
answer