

お世話になっております。  
Promiseの戻り値の扱い方を教えていただきたいです。

■やりたいこと  
Promiseで処理した配列の値を取得したい。

■プログラム  
外部JSONファイルに書かれた画像のパスにアクセスしてBase64Imageに変換（5回繰り返し）。←ここまでＯＫ  
変換したBase64Imageの文字列を渡して（←今ここ）、PDFに画像を表示させる予定。

■できないこと  
後述のプログラムで、  
`myData`に、

[code]

    img_image01:base64,iVBORw0KG(…中略…)'
    img_image02:base64,iVBORw0KG(…中略…)'
    img_image03:base64,iVBORw0KG(…中略…)'
    
[/code]

といった感じで、Base64Imageの文字列は渡せているのですが、

[code]

    console.log(resolvedata)
    
[/code]

すると、

[code]

    Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: Array(1)}
    
[/code]

と`Promise`でラップされてたものが出てきてしまいます。（マニュアルどうりですが。）

[code]

    Array(1)
    
[/code]

の部分だけ取り出して、配列として使いたいです。  
例えば、

[code]

    resolvedata['img_image01']
    
[/code]

とすると

[code]

    'data:image/png;base64,iVBORw0KG(…中略…)'
    
[/code]

が返ってくるイメージです。

[code]

    // ------------------------------------------------------------
    // Promiseで順番に画像を変換してmyDataに格納
    // ------------------------------------------------------------
    var resolvedata = getContent().then((myData) => {
        getBase64Image(myData[0]['path_img'], myData[0]['image01'], myData);
        return myData;
    }).then((myData) => {
        getBase64Image(myData[0]['path_img'], myData[0]['image02'], myData);
        return myData;
    })
    
            (…中略…)
    
    .then((myData) => {
        getBase64Image(myData[0]['path_img'], myData[0]['image05'], myData);
        return myData;
    }).catch(() => {console.log('error')});
    
    
    // ------------------------------------------------------------
    // 画像のパスが書かれた外部JSONファイルを取り込んでmyDataに格納　（Promise）
    // ------------------------------------------------------------
    function getContent() {
        return new Promise((resolve,reject) => {
            httpObj = new XMLHttpRequest();
            httpObj.open('get', '（任意のファイル）.json', true);
            httpObj.send(null);    
            httpObj.onload = function(){
                var myData = JSON.parse(this.responseText);
                resolve(myData);
            }
        });
    }
    
    // ------------------------------------------------------------
    // ファイルを指定してBase64に変換 (then)
    // ------------------------------------------------------------
    function getBase64Image(imgpath, imgfile, myData) {
        return new Promise((res,rej) => {
            if (imgfile == '') {
                res();
            } else{
                var path = imgpath;
                var thisimagekey = 'img_' + imgfile.split('.')[0];
                var getimg = '(任意のURL)' + path + '/' + imgfile;
    
                var encoding = false;
                if(encoding) return;
                encoding = true;
    
                var xhr = new XMLHttpRequest();
                xhr.open('GET',getimg);
                xhr.responseType = 'arraybuffer';
                xhr.send(null);
    
                xhr.onload = () => {
                    var array_buffer = xhr.response;
                    Base64_From_ArrayBuffer_Async(array_buffer,function(base64){
                        var data_url = 'data:' + xhr.getResponseHeader('Content-Type') +     ';base64,' + base64;    
                        myData[0][thisimagekey] = data_url;    
                    });    
                    res(myData);    
                };
            }
        });
    }
    
    // ------------------------------------------------------------
    // Base64に変換
    // ------------------------------------------------------------
    function Base64_From_ArrayBuffer_Async(ary_buffer,callback,increment){
        var dic = [
            'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
            'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
            'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
            'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
        ];
        var base64 = "";
        var ary_u8 = new Uint8Array( ary_buffer );
        var num = ary_u8.length;
        var n = 0;
        var b = 0;
    
        if(increment === undefined){
            increment = 10240;
        }
    
        var i = 0;
        var j = 0;
        function f(){
            while(i < num){
                b = ary_u8[i];
                base64 += dic[(b >> 2)];
                n = (b & 0x03) << 4;
                i ++;
                if(i >= num) break;
    
                b = ary_u8[i];
                base64 += dic[n | (b >> 4)];
                n = (b & 0x0f) << 2;
                i ++;
                if(i >= num) break;
    
                b = ary_u8[i];
                base64 += dic[n | (b >> 6)];
                base64 += dic[(b & 0x3f)];
                i ++;
    
                j += 3;
                if(j > increment){
                    j = 0;
                    setTimeout(f,1);
                    return;
                }
            }
    
            var m = num % 3;
            if(m){
                base64 += dic[n];
            }
            if(m == 1){
                base64 += "==";
            }else if(m == 2){
                base64 += "=";
            }
            callback(base64);
        }
        setTimeout(f,1);
    }
    
[/code]

何と書けば、`myData`を取り出せるのでしょうか。  
どうぞよろしくお願い致します。


CC BY-SA 3.0
2017-08-17T01:43:26.773
37261
2017-10-11T13:30:27.163
2017-08-17T03:00:34.250
21092
24521
question
javascript promise
Promiseで配列をreturnしたい


（下手な日本語で失礼します）

簡単に直すには、各`.then`をこう変えたらほぼ予想通りに動くと思います：

[code]

                      // v-- getBase64Imageを返します
    .then((myData) => getBase64Image(myData[0]['path_img'], myData[0]['image01'], myData))
    .then((myData) => getBase64Image(myData[0]['path_img'], myData[0]['image02'], myData))
    
[/code]

そして最後にこうします

[code]

    resolveData.then(result => console.log(result));
    
[/code]

一番間違っているところといえば、`getBase64Image()`にpromiseを作って`return`しているけど、そのpromiseの結果を待っていません。`then`内にpromiseを返せば、そのpromiseの処理が終わってから次の`then`が実行されます。

少し付け加えますと、以上のコードをもう少しきれいに書く方法があります。

とても似た部分を５回繰り返していますが、`Promise.all`を使うことで、配列をもう少し配列っぽく扱って、並列処理ができます。（そして並列処理のおかげで、少し早くなる可能性もあります）

[code]

    getContent().then((myData) =>
        // 全部のgetbase64Imageを待つ
        Promise.all([1, 2, 3, 4, 5].map(num => 
            getBase64Image(myData[0]['path_img'], myData[0]['image0' + num], myData)
        ))
        .then(() => myData)
    ).then((myData) => {
        console.log(myData);
    });
    
[/code]


CC BY-SA 3.0
2017-10-11T13:30:27.163
38605
2017-10-11T13:30:27.163
4788
37261
answer