await返回值与reduce参数

    async function taskReducer(promise, action){
        console.log('promise: '+ promise);
        let res = await promise;
        console.log('res: '+ res);
        return action(res);
    }

    function sleep(ms){
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    async function asyncTask(i){
        await sleep(500);
        console.log(`task ${i} done`);
        return ++i;
    }

    [asyncTask, asyncTask, asyncTask].reduce(taskReducer, 0);

执行结果为:
图片描述

taskReducer第1次执行时,promise=0;action为asyncTask,参数为0,taskReducer中打印出的promise为0,res为0,taskReducer返回action(res),即 asyncTask(0),输出task 0 done,同时asyncTask(0)返回1,说明第一次执行taskReducer返回值为1;

问题

  1. taskReducer第2次执行时,promise打印出的值为什么是Promise对象,Promise对象是哪里来的?为什么不是上次taskReducer的返回值1?

  2. taskReducer第2次执行时,promise打印出的值为什么是Promise对象,而res = await promise;res为什么打印出1?

猜想

因为taskReducer是异步函数async,而reduce是同步执行的,所以说taskReducer未返回之前,reduce已经执行完成了,而console.log('promise: '+promise);是taskReducer中的同步代码,因此也会同步自行,而reduce执行时必须用到上次taskReducer的返回值,而taskReducer又不能立即返回,所以taskReducer就默认返回Promise对象?等到taskReducer中 let res = await promise执行完成有返回值的时候,正好输出res?

阅读 2.7k
1 个回答

你对async和await的理解有问题

async/await只是个语法糖,async关键字修饰的函数会把返回值包装成promise,而await关键字作用于promise上时,表达式的结果就是promise.resolve,可以简单理解调用了promise.then,但把then接收到的参数拿了出来

所以你的问题
1.第一次asyncTask(0)返回的不是1,而是

return new Promise(resolve => {
    sleep(500).then(_ => {
        console.log(`task ${i} done`);
        resolve(++i);
    })
})

2.为什么打印Promise对象,就是第一个的答案;res为什么是1,就是await关键字的作用;至于第一次调用,promise参数为0时,因为那时promise参数不是Promise对象,所以await关键字被忽略了

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题