嵌套异步jQuery Promise [英] Nesting asynchronous jquery promises

查看:113
本文介绍了嵌套异步jQuery Promise的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了一个小程序来帮助我了解如何在jquery中执行嵌套的异步Promise.

I've written a little program to help me understand how to do nested asynchronous promises in jquery.

我想依次调用两个任务.第一个任务有两个子任务,这些子任务也被依次调用.就是这样.

I want to call two tasks, in sequence. The first task has two subtasks that also are called in sequence. That's all.

虽然这行得通,但我怀疑这是否是使用诺言的最佳方式.必须为每个任务创建一个新的延迟的感觉对我来说就像是代码的味道.例如,最好是传递单个延迟的对象,然后仅使用该对象?谢谢!

While this works, I have doubts as to whether this was the best way to use promises. Having to create a new deferred for every task feels like code smell to me. For example, would it be better to pass a single deferred object around and use only that? Thanks!

https://plnkr.co/edit/dyFFqqZhCVuhBYCuWjzm?p=preview

doTasks().then(function(arg) {
    console.log(arg)
})

function doTasks() {
    var d = $.Deferred();
    task1().then(function(arg) {
        console.log(arg)
        task2().then(function(arg) {
            console.log(arg)
            d.resolve('all tasks are done')
        })
    })
    return d.promise();
}

function task1() {
    var d = $.Deferred();

    console.log("starting task1...")

    setTimeout(function() {
        task1A().then(function() {
            task1B().then(function() {
                d.resolve('task1 is done')
            })
        })
    }, 10);

    return d.promise();
}

function task1A() {
    var d = $.Deferred();
    console.log("starting task1A...")
    setTimeout(function() {
        console.log("  resolving task1A...")
        d.resolve();
    }, 1000);
    return d.promise();
}

function task1B() {
    var d = $.Deferred();
    console.log("starting task1B...")
    setTimeout(function() {
        console.log("  resolving task1B...")
        d.resolve();
    }, 1000);
    return d.promise();
}

function task2() {
    var d = $.Deferred();
    console.log("starting task2...")

    setTimeout(function() {
        d.resolve('task2 is done');
    }, 1000);
    return d.promise()
}

推荐答案

是的,创建许多不必要的延期有点臭.

Yes, it is a bit smelly to create a lot of unnecessary deferreds.

您不需要为ajax操作创建任何延期.如果您从.then()处理程序中返回一个Promise,它将自动链接到先前的Promise(从而对其进行排序),并且所有jquery ajax调用都已经返回了Promise.因此,您无需为ajax操作创建任何自己的Promise.而且,您可以链接而不是嵌套以便对操作进行排序.

You don't need to create any deferreds for your ajax operations. If you return a promise from within a .then() handler, it is automatically chained to the previous promise (thus sequencing it) and all jquery ajax calls already return promises. So you don't need to create any of your own promises for the ajax operations. And, you can chain rather than nest in order to sequence your operations.

实际上,在不需要时创建延期或承诺被称为

In fact, creating deferreds or promises when you don't need to is referred to as a promise anti-pattern. You want to use and return the promises that are already created rather than make new ones. And, where possible, you want to chain your promises rather than nest.

在这里,您可以在可运行的代码段中执行此操作,而无需创建一个递延的代码,只有一个地方可以将setTimeout()包装在promise中.显然,如果为它们创建了可重用的函数,则可以为所有任务使用更少的代码,但我假设这些只是真正的异步操作的占位符,因此我将其保留为原样(除非共享的delay()函数).

Here's how you can do that in a runnable snippet without creating a single deferred except one place to wrap setTimeout() in a promise. Obviously, you could use a lot less code for all your tasks if you created a re-usable function for them, but I'm assuming those are just placeholders for the real async operations so I'll leave them as is (except use the shared delay() function).

doTasks().then(function(arg) {
    console.log("everything done");
})

function doTasks() {
    return task1().then(function(arg) {
        console.log(arg);
        return task2().then(function(arg) {
            console.log(arg)
            return arg;
        })
    })
}

// make promise version of setTimeout() in one central place
// that can then be used elsewhere
function delay(t) {
    return $.Deferred(function(def) {
        setTimeout(function() {
            def.resolve();
        }, t);
    }).promise();
}

function task1() {
    console.log("starting task1...")
    return delay(10).then(function() {
        return task1A();
    }).then(function() {
        return task1B();
    });
}

function task1A() {
    console.log("starting task1A...")
    return delay(1000).then(function() {
        console.log("  resolving task1A...")
        return "done task1A";
    });
}

function task1B() {
    console.log("starting task1B...")
    return delay(1000).then(function() {
        console.log("  resolving task1B...")
        return "done task1B";
    });
}

function task2() {
    console.log("starting task2...")
    return delay(1000).then(function() {
        console.log("  task2 is done")
        return "done task2";
    });
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

这篇关于嵌套异步jQuery Promise的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆