使用promise.all节点异步/等待

时间:2018-04-20 17:32:33

标签: javascript node.js async-await es6-promise

在一个简单的JS程序中,我需要让asyncOperation2和asyncOperation3与asyncOperation1一起顺序执行。意思是我需要做以下事情:

1) order of execution as  1,2,3 or 2,3,1
2) then after step 1. I need to preform an operation on the result of 1,2,3

这是我到目前为止所拥有的(这将在Node中运行)。但是我不能像上面描述的那样让操作顺序发生。

const App = {
    total: 0,

    init: function () {
        // I want to run all 3 operations. (with 2 and 3 happening sequentially)
        Promise.all([App.asyncOperation1(1000), App.combine2and3()])
            .then((total) => {
                // then I want to use the result of all 3 operations
                console.log(`total from top: ${total}`);
            })
    },

    asyncOperation1: function (time) {
        return new Promise(function (resolve, reject) {
            var intervalID = setTimeout(function () {
                resolve(time);
            }, time);
        });
    },

    asyncOperation2: async function (time) {
        setTimeout(function () {
            return time;
        }, time);
    },

    asyncOperation3: async function (time) {
        setTimeout(function () {
            return time;
        }, time);
    },

    combine2and3: async function () {
        var value2 = await App.asyncOperation2(2000);
        var value3 = await App.asyncOperation3(1000);
        console.log(`value2: ${value2}`)
        console.log(`value3: ${value3}`)
        console.log(`summed total ${value2 + value3}`);
        return value2 + value3;
    },
};

App.init();

实际结果:

value2: undefined
value3: undefined
summed total NaN
total from top: 1000,NaN

期望的结果:

value2: 2000
value3: 1000
summed total 3000
total from top: 1000,3000

3 个答案:

答案 0 :(得分:2)

如果您想要返回某个值,

asyncOperation2asyncOperation3应解决承诺。 (你在combine2and2中做了什么)。

PS。从setTimeout返回一些值是错误的。你不能这样做

将它们包裹在Promise中并解析您想要从中返回的值。

这样的东西

const App = {
    total: 0,

    init: function () {
        // I want to run all 3 operations. (with 2 and 3 happening sequentially)
        Promise.all([App.asyncOperation1(1000), App.combine2and3()])
            .then((total) => {
                // then I want to use the result of all 3 operations
                console.log(`total from top: ${total}`);
            })
    },

    asyncOperation1: function (time) {
        return new Promise(function (resolve, reject) {
            var intervalID = setTimeout(function () {
                resolve(time);
            }, time);
        });
    },

    asyncOperation2:  function (time) {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            resolve(time);
        }, time);
        });
    },

    asyncOperation3:  function (time) {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            resolve(time);
        }, time);
        })
    },

    combine2and3: async function () {
        var value2 = await App.asyncOperation2(2000);
        var value3 = await App.asyncOperation3(1000);
        console.log(`value2: ${value2}`)
        console.log(`value3: ${value3}`)
        console.log(`summed total ${value2 + value3}`);
        return value2 + value3;
    },
};

App.init();

答案 1 :(得分:2)

问题是asyncOperation2()asyncOperation3()会返回一个承诺 (因为他们的async声明)没有解析的值(因此它是undefined),因为这些函数没有自己的返回值。

asyncOperation2: async function (time) {
    setTimeout(function () {
        return time;     // this just returns back into the timer sub-system
    }, time);
    // there is no return value for your function here
    // thus the promise the async function returns has an undefined resolved value
},

setTimeout()内部返回不是函数的返回值。这只是返回到函数本身返回很久之后发生的计时器内部。请记住,setTimeout()是非阻止的。它安排一些代码在将来的某个时间运行,然后立即返回,然后你的函数完成并返回(在setTimeout()被触发之前)。所以,稍后一段时间后,你的setTimeout()会触发并从该回调中返回一个值,该值只会返回到计时器子系统,而不是任何代码或任何承诺。

将这两个功能更改为:

function delay(t, v) {
   return new Promise(resolve => {
       setTimeout(resolve.bind(null, v));
   }, t);
}

asyncOperation2: function (time) {
    return delay(time, time);
},

asyncOperation3: function (time) {
    return delay(time, time);
},

现在您有了返回使用所需值解析的promise的函数。注意,它们不需要声明为async,因为你没有在函数内部使用await而你已经创建了自己的返回承诺。

答案 2 :(得分:0)

当回调函数中的return time传递给setTimeout时,只返回回调函数,而不是外部函数。您必须将setTimeout调用包含在承诺中,例如在asyncOperation1中。您还可以创建辅助函数以避免重复。



const wait = time => new Promise(
  resolve => setTimeout(() => resolve(time), time)
);

const App = {
    total: 0,

    init: function () {
        // I want to run all 3 operations. (with 2 and 3 happening sequentially)
        Promise.all([App.asyncOperation1(1000), App.combine2and3()])
            .then((total) => {
                // then I want to use the result of all 3 operations
                console.log(`total from top: ${total}`);
            })
    },

    asyncOperation1: wait,

    asyncOperation2: wait,

    asyncOperation3: wait,

    combine2and3: async function () {
        var value2 = await App.asyncOperation2(2000);
        var value3 = await App.asyncOperation3(1000);
        console.log(`value2: ${value2}`)
        console.log(`value3: ${value3}`)
        console.log(`summed total ${value2 + value3}`);
        return value2 + value3;
    },
};

App.init();