账号密码登录
微信安全登录
微信扫描二维码登录

登录后绑定QQ、微信即可实现信息互通

手机验证码登录
找回密码返回
邮箱找回 手机找回
注册账号返回
其他登录方式
分享
  • 收藏
    X
    js中async await声明方法中,关于嵌套循环的复杂情景问题求教?
    59
    0

    1、问题情景:

    今天在写代码的时候遇到一个比较复杂的问题,我简化后总结如下:
    例子:现在我们已经封装了两个函数接口,timeout延时函数与output函数,需求就是在第三个函数eachTest中根据需求调用上述两个已封装好的接口,代码如下:

    已封装的代码:

    function timeout (millisec) {
        const timeo = new Promise(function(resolve, reject){
            if (typeof millisec != 'number') {
                reject('输入必须是数字类型');
            }
            setTimeout(function () {
                resolve(`延时了${millisec}毫秒后输出`)
            }, millisec)
        });
        return timeo;
    }
    
    function output (millisec, callback) {
         timeout(millisec).then(function (result) {
            callback(result);
        })
    }

    我进行编写的代码(需要循环):

    async function eachTest () {
        let arr = []; // 这里定义一个需要的数组
        for (let i = 0; i < 5; i++) {
            await output(1000, function (res) {
                arr.push(res); // 我想在这里循环调用output的方法,
                //把返回回调的值存到数组中,同时把数组返回供外部调用
            });
        }
        return arr;
    }
    
    eachTest().then(function(res){
        // 我需要在这里获取上述的eachTest返回的数组,应该怎么拿到?
        console.log(res);
    })

    我的问题?

    大部分的问题都写在上面的注释中了,这里再简单说一下:
    我需要在eachTest().then的函数后输入我这需要的数组,但是我每次都发现,先输出的是arr=[]也就是空数组,也就是说先执行了then,(我这里猜测是promise嵌套的问题吗?)并不是我需要的填满数组的数据,也许我是对async还不够熟悉的原因,自己找不到解决方案。
    PS:我个人理解的解决方案是在function ouput前加入async关键字,但是我们秉承着不改变原函数接口的理念,就放弃了这个方案。
    求教各位大神,有没有好一点的方案解决我的需求,谢谢了!

    0
    打赏
    收藏
    点击回答
    您的回答被采纳后将获得:提问者悬赏的 10 元积分
        全部回答
    • 0
    • 莫笑年少江湖梦 普通会员 1楼

      在JavaScript中,async/await是ES2017引入的一种语法糖,它使异步代码看起来像同步代码。在async/await中,你可以在async函数内部使用async函数或await关键字来声明一个函数,这个函数可以接受一个Promise对象作为参数,或者直接返回一个Promise对象。以下是一个使用嵌套循环的复杂情景的例子:

      ``javascript async function outerFunction() { try { const promises = []; for (let i = 0; i < 5; i++) { promises.push(async () => { try { const result = await innerFunction(); console.log(Inner function result: ${result}); } catch (error) { console.error(Inner function error: ${error}); } })(); } await Promise.all(promises); } catch (error) { console.error(Outer function error: ${error}`); } }

      outerFunction(); ```

      在这个例子中,outerFunction是一个异步函数,它内部定义了一个嵌套的Promise循环。innerFunction是一个返回Promise的函数,它的返回值是另一个Promise对象,它在每次迭代中调用自身,然后在每次迭代完成后获取内部Promise的值,并将其打印到控制台。

      outerFunction的try-catch块中,我们首先创建了一个空的Promise数组promises,然后使用for循环迭代5次,每个循环迭代一次innerFunction。在循环内部,我们使用await关键字来等待innerFunction的返回值。如果innerFunction内部出现错误,Promise rejection会引发一个异常,此时Promise.all方法会阻塞当前的代码块,直到所有Promise都resolve或reject。

      当所有的Promise都resolve时,Promise.all方法会调用outerFunction的finally块,这个finally块中会执行一些清理任务,如关闭文件句柄、清除内存等,然后执行outerFunction。如果outerFunction内部出现了错误,Promise.all方法会捕获到这个异常,并将其打印到控制台。

      注意,await关键字在异步代码中非常重要,它使得异步代码看起来像同步代码,从而提高了代码的可读性和可维护性。但是,过度使用await关键字可能会导致代码变得复杂和难以理解,特别是在处理嵌套循环或复杂的Promise结构时。在这种情况下,你可能需要考虑使用其他方法来处理嵌套循环,如使用Promise.allSettled,Promise.all解决,或者使用Promise.allRejection,这些方法在处理复杂Promise结构时更加高效和简洁。

    更多回答
    扫一扫访问手机版
    • 回到顶部
    • 回到顶部