在JavaScript中使用Promises运行代码时出现问题

时间:2020-05-03 19:14:41

标签: javascript asynchronous promise async-await reduce

程序说明

Create 3 functions:
FuncA – will receive a string and returns it’s length
FuncB – will receive an array of strings and returns their total lengths (using
funcA) after 2 seconds.
FuncC - will receive an array of arrays of strings and returns their total lengths
(using FuncB)

我的解决方案是

    function funcA(s)
    {
        return s.length
    }

    function funcB(arr)
    {
        return new Promise(resolve =>
            {
                setTimeout(() =>
                {
                    let total = 0;
                    arr.forEach(element => {
                        total += funcA(element)
                    });
                    resolve(total)
                },2000)
            })
    }

    function funcC(arr)
    {      
            return new Promise(resolve =>
                {
                    let isFirst = true
                    //a <=> total
                    let total = arr.reduce(async (a,b) =>
                    {
                        if(isFirst) {
                           isFirst = false
                           return (await funcB(a) + await funcB(b))
                        }
                        else {//a <=> total
                            return (a + await funcB(b))
                        }
                    })
                    resolve(total)
                }) 
    }

正在运行:
funcC([[“ aa”,“ bbb”,“ tyui”],[“ ccc”],[“ dfghj”,“ aedtfr”]])。then(x => console.log(x))

结果是: [object Promise] 11

出了什么问题?

2 个答案:

答案 0 :(得分:1)

这真令人费解。

  • 请勿将业务逻辑放入setTimeout回调中。仅解决承诺,然后在承诺then回调中或在await之后进行工作。
  • 始终将初始值传递给reduce!这将使其与空数组一起使用,并且将不再需要真正奇怪的isFirst逻辑。
  • total已经是一个承诺。不必将其包装在new Promise中!

这些建议将导致

function funcA(s) { return s.length }

function funcB(arr) {
    return new Promise(resolve => {
        setTimeout(resolve, 2000);
    }).then(() => {
        let total = 0;
        arr.forEach(element => {
            total += funcA(element)
        });
        return total;
    });
}

function funcC(arr) {      
    return arr.reduce(async (a,b) => {
        return await a + await funcB(b)
    }, Promise.resolve(0))
}

但是,reduce is not really suited for asynchronous work。您应该在funcC中使用循环方法,而在reduce中使用funcB更适合:

async function funcB(arr) {
    await new Promise(resolve => {
        setTimeout(resolve, 2000);
    });
    return arr.reduce((total, element) => total + funcA(element), 0);
}

async function funcC(arr) {
    let total = 0;
    for (const b of arr) {
        total += funcB(b);
    }
    return total;
}

答案 1 :(得分:0)

[固定答案]

您应该在所有地方都使用await a而不是a

function funcC(arr)
{      
    return new Promise(resolve =>
        {
            let isFirst = true
            //a <=> total
            let total = arr.reduce(async (a,b) =>
            {
                if(isFirst) {
                    isFirst = false
                    return (await funcB(await a) + await funcB(b))
                }
                else {//a <=> total
                    return (await a + await funcB(b))
                }
            })
            resolve(total)
        }) 
}