One Promise按顺序调用未知(动态)数量的异步方法

时间:2017-10-31 15:39:48

标签: javascript promise

我想创建一个Promise,它在内部按顺序调用一系列异步方法,并在最后一个方法返回后返回这些方法的结果,并在有序数组中连接。

我正在尝试这个:

const getArray = function (thisArray) {
    return new Promise ( function (resolve, reject) {
        if (thisArray.length < 3) {
            setTimeout(function() {
                console.log('adding element');
                thisArray.push(thisArray.length);
                getArray(thisArray);
            },  1000); 
        } else {
            console.log(thisArray);
            console.log('resolving');
            resolve(thisArray);
        }
    });
}

getArray([]).then(function(data) {
    console.log('thened');
    console.log(data);
})

但它永远不会调用then()。我怎么能这样做?

1 个答案:

答案 0 :(得分:1)

你根本不远,你只需要确保为每个resolve致电new Promise。如果您仍在构建数组,则会从递归getArray调用中传递生成的承诺;否则,你传递数组:

const getArray = function(thisArray) {
    return new Promise((resolve, reject) => {
        if (thisArray.length >= 3) {
            // All done
            resolve(thisArray);
        } else {
            // Do something async...
            setTimeout(() => {
                // ...add the result
                console.log('adding element');
                thisArray.push(thisArray.length);
                // ...and recurse
                resolve(getArray(thisArray));
            }, 1000);
        }
    });
}

getArray([]).then(data => {
    console.log('done');
    console.log(data);
});

如果将执行异步工作的函数与getArray分开,并且确保执行异步工作的函数返回一个promise,那就更清晰了。出于我们的目的,我们可以将setTimeout包装在Promise包装器中:

const setTimeoutP = (cb, delay) => {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve(cb());
        }, delay);
    });
};

然后:

const getArray = thisArray => {
    if (thisArray.length >= 3) {
        return Promise.resolve(thisArray);
    }
    return setTimeoutP(() => {
        console.log("adding element");
        thisArray.push(thisArray.length);
    });
};

实时复制:

const setTimeoutP = (cb, delay) => {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve(cb());
        }, delay);
    });
};

const getArray = thisArray => {
    if (thisArray.length >= 3) {
        return Promise.resolve(thisArray);
    }
    return setTimeoutP(() => {
        console.log("adding element");
        thisArray.push(thisArray.length);
        return getArray(thisArray);
    }, 1000);
};

getArray([]).then(data => {
    console.log('done');
    console.log(data);
});