skip to Main Content

I tried below code where inside replace method fetch api call is happening and it returning response and based on response returning <img>. But issue is its returning [object Promise]

 str.replace(/!([^|!]*(?:jpe?g|png|gif|mp4|mp3|mkv|mov))(?:|width=(d*.?d+%?)(?:,height=(d*.?d+%?))?)?!/gm,  async (match, capture) => {
                let m, reg = /!([^|!]*(?:jpe?g|png|gif|mp4|mp3|mkv|mov))(?:|width=(d*.?d+%?)(?:,height=(d*.?d+%?))?)?!/gm;
                let imageConfig = [];
                while ((m = reg.exec(str)) !== null) {
                    imageConfig.push({ file: m[1], width: (m[2] || ''), height: (m[3] || '') });
                }
                let payload = {
                    'columns': [
                        {
                            'id': columnMeta.id,
                            'values': [
                                { "type": "@thumbnail", "values": imageConfig.map(e => e?.file) },
                            ]
                        }
                    ]
                }
                payload.rowId = rowData?.id;
                let reolvedFile = [];
                let response = await Service.post(
                    generateAPIURL({
                        boardId: TableHelper.getwrapperConfig?.boardId,
                        tableId: TableHelper.getwrapperConfig?.tableId,
                        columnId: columnMeta?.id,
                        type: "getresolvedValue",
                    }),
                    null,
                    JSON.stringify({ ...payload })
                )
                let values = response?.columns?.[0]?.values;
                imageConfig.map(e => e?.file)?.map(o => {
                    let index = values?.findIndex(e => e?.name === o);
                    if (index !== -1) {
                        reolvedFile.push(values[index]);
                    }
                })
                
                //Find the matching entry
                var info = reolvedFile?.find(({ name }) => name === capture);
                let width = imageConfig.find((e) => e?.file === capture)?.width || 200;
                let height = imageConfig.find((e) => e?.file === capture)?.height || 200;
                return info ?
                    `<img src="${info?.thumbnail}"   data-name="${info?.name}"  width=${width} height=${height} style="width:'${width}px';height:'${height}px';display: inline-block;"/>`
                    : `<div  id="${capture}" data-name="${capture}" class="linear-background" style="width:'${width}px';height:'${height}px';display: inline-block;" ></div>`;
            })

I tried above code and expecting it should return <img> after response comes instead of [object Promise]

return info 
    ? `<img src="${info?.thumbnail}"   data-name="${info?.name}"  width=${width} height=${height} style="width:'${width}px';height:'${height}px';display: inline-block;"/>`
    : `<div  id="${capture}" data-name="${capture}" class="linear-background" style="width:'${width}px';height:'${height}px';display: inline-block;" ></div>`;

3

Answers


  1. String#replace has no provision to await for a replacer function’s returned promise to finish – and you are returning a promise, since the replacer is async.

    You’ll need something that can deal with this, e.g.

    async function asyncStringReplace(string, pattern, replacer) {
      
      const promises = [];
      // Find all replacements once (discarding the result),
      // but keeping track of the promises that will eventually
      // resolve to the replacement values
      string.replace(pattern, (match, ...args) => {
        promises.push(replacer(match, ...args));
      });
      // Await for all of the gathered promises to resolve
      const replacements = await Promise.all(promises);
      // Run the replacement again, draining the replacements array
      return string.replace(pattern, () => replacements.shift());
    }
    
    async function fetchResultForMatch(m) {
      // pretend we'd fetch something from the network
      return m.toUpperCase() + "!";
    }
    
    async function main() {
      const string = "hello world, all words longer than five letters in this text should be screamy";
      const result = await asyncStringReplace(string, /w{5,}/g, fetchResultForMatch);
      console.log(result);
    }
    
    main();
    Login or Signup to reply.
  2. You can use String#matchAll() to map matches to their replaced counterparts with an async callback:

    const replace = (str, regex, replace) => 
      Promise.all([...str.matchAll(regex), {index: str.length}].map(async (m, i, arr) => 
        str.slice(i ? arr[i-1].index + arr[i-1][0].length : 0, m.index) + (m ? await replace(m) : '')
    )).then(r => r.join(''));
    
    replace(
      '---1,2,3,4,5---', 
      /d+/g,
      m => new Promise(r => setTimeout(() => r('X'.repeat(m[0])), 500))
    ).then(r => console.log(r));
    Login or Signup to reply.
  3. The capture from the regex match hasn’t been used before the await API call. You do not want to call an API in a string substitution function that it may cause a serious waste of network resources.

    Consider moving all irrelevent statements including await calls outside of replace function scope.

    How the structure could be changed based on your code:

    async function main() {
        /* move all irrelevent statements outside of replace function -- START */
        let m, reg = /!([^|!]*(?:jpe?g|png|gif|mp4|mp3|mkv|mov))(?:|width=(d*.?d+%?)(?:,height=(d*.?d+%?))?)?!/gm;
        let imageConfig = [];
        while ((m = reg.exec(str)) !== null) {
            imageConfig.push({ file: m[1], width: (m[2] || ''), height: (m[3] || '') });
        }
        let payload = {
            'columns': [
                {
                    'id': columnMeta.id,
                    'values': [
                        { "type": "@thumbnail", "values": imageConfig.map(e => e?.file) },
                    ]
                }
            ]
        }
        payload.rowId = rowData?.id;
        let reolvedFile = [];
        let response = await Service.post(
            generateAPIURL({
                boardId: TableHelper.getwrapperConfig?.boardId,
                tableId: TableHelper.getwrapperConfig?.tableId,
                columnId: columnMeta?.id,
                type: "getresolvedValue",
            }),
            null,
            JSON.stringify({ ...payload })
        )
    
        let values = response?.columns?.[0]?.values;
    
        imageConfig.map(e => e?.file)?.map(o => {
            let index = values?.findIndex(e => e?.name === o);
            if (index !== -1) {
                reolvedFile.push(values[index]);
            }
        });
        /* move all irrelevent statements outside of replace function -- END */
    
        return str.replace(reg, (match, capture) => {
            //Find the matching entry
            var info = reolvedFile?.find(({ name }) => name === capture);
            let width = imageConfig.find((e) => e?.file === capture)?.width || 200;
            let height = imageConfig.find((e) => e?.file === capture)?.height || 200;
            return info ?
                `<img src="${info?.thumbnail}"   data-name="${info?.name}"  width=${width} height=${height} style="width:'${width}px';height:'${height}px';display: inline-block;"/>`
                : `<div  id="${capture}" data-name="${capture}" class="linear-background" style="width:'${width}px';height:'${height}px';display: inline-block;" ></div>`;
        })
    }
    
    main();
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search