且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

结合异步动作,promise.then()和递归setTimeout,同时避免“延迟反模式".

更新时间:2022-12-16 16:44:49

我认为您快到了,看来您只是在为JavaScript的异步特性而苦苦挣扎.肯定会使用诺言,理解如何将诺言链接在一起是实现用例的关键.

I think you're almost there, it seems you're just struggling with the asynchronous nature of javascript. Using promises is definitely the way to go here and understanding how to chain them together is key to implementing your use case.

我将从实现包装setTimeout的单一方法开始,以简化操作.

I would start by implementing a single method that wraps setTimeout to simplify things down.

function delay(millis) {
    return new Promise((resolve) => setTimeout(resolve, millis));
}

然后,您可以使用delay函数重新实现"API"方法.

Then you can re-implement the "API" methods using the delay function.

const userIdApi = () => {
    return delay(2000).then(() => "uid123");
};

// Make userId an argument to this method (like pollDatabase) so we don't need to get it twice.
const startProcessingTaskApi = (userId) => {
    return delay(2000).then(() => "Task submitted");
};

const pollDatabase = (userId) => {
    return delay(2000).then(() => true);
};

只要不满足您的条件,您只需在链中链接另一个promise,就可以继续轮询数据库.

You can continue polling the database by simply chaining another promise in the chain when your condition is not met.

function pollUntilComplete(userId) {
    return pollDatabase(userId).then((result) => {
        if (!result) {
            // Result is not ready yet, chain another database polling promise.
            return pollUntilComplete(userId);
        }
    });
}

然后,您可以将所有内容放在一起以实现用例.

Then you can put everything together to implement your use case.

userIdApi().then((userId) => {
    // Add task processing to the promise chain.
    return startProcessingTaskApi(userId).then(() => {
        // Add database polling to the promise chain.
        return pollUntilComplete(userId);
    });
}).then(() => {
    // Everything is done at this point.
    console.log('done');
}).catch((err) => {
    // An error occurred at some point in the promise chain.
    console.error(err);
});