如何避免硬codeD,在Javascript / jQuery的链式异步函数? [英] How to avoid hard-coded, chained asynchronous functions in Javascript/jQuery?

查看:171
本文介绍了如何避免硬codeD,在Javascript / jQuery的链式异步函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

几乎所有在我的程序中的功能有某种异步调用,但它们都依赖于一些previous作用的结果。这一点,因为,我已经硬codeD的下一个函数调用到每一个人一个作为这样的:

Almost all of the functions in my program have some sort of asynchronous call, but they all rely on some previous function's results. Because of that, I've hard-coded the next function call into each individual one as such:

function getStuff() {
    $.ajax({
        ...
        success: function(results) {
            // other functions involving results
            getMoreStuff(results);
        }
    });
}

function getMoreStuff(results) {
    $.ajax({
        ...
        success: function(moreResults) {
            // other functions involving moreResults
            doSomethingWithStuff(moreResults);
        }
    );
}

等。这是一家大型连锁其中每个函数调用下。虽然这个工作计划中,它使每个单独的功能形同虚设。

And so on. It's a large chain where each function calls the next. While this works within the program, it makes each function useless individually.

我有点失去了关于如何避免这个问题。我无法弄清楚如何使用一般的回调函数,因为当我做的函数调用,它结束了像这样(使用上述功能):

I'm a bit lost on how to avoid this problem. I couldn't figure out how to use general callback functions, because when I make the function calls, it ends up like this (using the functions above):

getStuff(function() {
    getMoreStuff(results, doSomethingWithStuff);
};

不过,结果还没有被定义。

But then 'results' hasn't been defined yet.

该解决方案似乎是显而易见的,我只是作为一个有点密集了。对不起!

The solution seems obvious, I'm just being a bit dense about it. Sorry!

推荐答案

您有几个选择。你可以有你的code。使用这些功能看起来像这样,通过回调:

Overview

You have a couple of choices. You can have your code using those functions look like this, using callbacks:

getStuff(function(results) {
    getMoreStuff(results, doSomethingWithStuff);
});

或类似这样的,使用jQuery的延迟无极目标:

getStuff().then(getMoreStuff).then(doSomethingWithStuff):

使用回调

同时拥有 getStuff getMoreStuff 接受一个参数是一个回调,当他们完成调用,如

Using callbacks

Have both getStuff and getMoreStuff accept an argument that is a callback to call when they're done, e.g.:

function getStuff(callback) {
//                ^------------------------------ callback argument
    $.ajax({
        ...
        success: function(results) {
            // other functions involving results
            callback(results);
//          ^------------------------------------ use the callback arg
        }
    });
}

......,同样为 getMoreStuff

jQuery的 AJAX 功能集成了延迟无极功能。你可以再补充返回将现有的功能,使这项工作,例如:

jQuery's ajax function integrates with its Deferred and Promise features. You can just add return to your existing functions to make that work, e.g.:

function getStuff(callback) {
    return $.ajax({
        ...
    });
}

(注意:没有必要在成功回调)

(Note: No need for the success callback.)

那么这code:

getStuff().then(getMoreStuff).then(doSomethingWithStuff);

做到这一点:

does this:

  1. getStuff 开始其 AJAX 呼叫并返回无极的调用创建。

  1. getStuff starts its ajax call and returns the Promise that call creates.

在该 AJAX 调用完成和解决的承诺, getMoreStuff 被调用的结果 AJAX 通话作为第一个参数。它开始的及其 AJAX 电话。

When that ajax call completes and resolves the promise, getMoreStuff is called with the results of the ajax call as its first argument. It starts its ajax call.

getMoreStuff AJAX 调用完成, doSomethingWithStuff 被调用的结果的的调用(一个在 getMoreStuff )。

When getMoreStuff's ajax call completes, doSomethingWithStuff is called with the results of that call (the one in getMoreStuff).

要使用重要的是然后,不是完成,以获得在每个阶段传递正确的结果。 (如果你使用完成,无论 getMoreStuff doSomethingWithStuff 将看到 getStuff 的 AJAX 电话。)

It's important to use then, not done, in order to get the correct results passed on at each stage. (If you use done, both getMoreStuff and doSomethingWithStuff will see the results of getStuff's ajax call.)

下面是一个使用一个完整的示例 AJAX

Here's a full example using ajax:

小提琴 | 备用摆弄 AJAX 通话服用,每次一秒钟(使得它更容易看看发生了什么)

Fiddle | Alternate Fiddle with the ajax calls taking one second each (makes it easier to see what's happening)

function getStuff() {
    display("getStuff starting ajax")
    return $.ajax({
        url: "/echo/json/",
        type: "POST",
        data: {json: '{"message": "data from first request"}'},
        dataType: "json"
    });
}

function getMoreStuff(results) {
    display("getMoreStuff got " + results.message + ", starting ajax");
    return $.ajax({
        url: "/echo/json/",
        type: "POST",
        data: {json: '{"message": "data from second request"}'},
        dataType: "json"
    });
}

function doSomethingWithStuff(results) {
    display("doSomethingWithStuff got " + results.message);
}

getStuff().then(getMoreStuff).then(doSomethingWithStuff);

function display(msg) {
    var p = document.createElement('p');
    p.innerHTML = String(msg);
    document.body.appendChild(p);
}

输出:

getStuff starting ajax

getMoreStuff got data from first request, starting ajax

doSomethingWithStuff got data from second request

您不需要使用 AJAX 来获得这样的好处,你可以用你自己的延迟无极的对象,它可以让你写这样的链条:

You don't need to be using ajax to get the benefit of this, you can use your own Deferred and Promise objects, which lets you write chains like this:

one().then(two).then(three);

......任何情况下,你可能有异步的完成。

...for any situation where you may have asynchronous completions.

下面是一个非 - AJAX 例如:

Here's a non-ajax example:

小提琴

function one() {
    var d = new $.Deferred();
    display("one running");
    setTimeout(function() {
      display("one resolving");
      d.resolve("one");
    }, 1000);
    return d.promise();
}

function two(arg) {
    var d = new $.Deferred();
    display("Two: Got '" + arg + "'");
    setTimeout(function() {
      display("two resolving");
      d.resolve("two");
    }, 500);
    return d.promise();
}

function three(arg) {
    var d = new $.Deferred();
    display("Three: Got '" + arg + "'");
    setTimeout(function() {
      display("three resolving");
      d.resolve("three");
    }, 500);
    return d.promise();
}

one().then(two).then(three);

function display(msg) {
    var p = document.createElement('p');
    p.innerHTML = String(msg);
    document.body.appendChild(p);
}

输出:

one running

one resolving

Two: Got 'one'

two resolving

Three: Got 'two'

three resolving

这两个(即 AJAX 例如,非 - AJAX 为例)可以结合在必要时。举例来说,如果我们把 getStuff AJAX 的例子,我们决定我们之前做数据的一些处理我们把这项工作交给 getMoreStuff ,我们会改变这样的:小提琴

These two (the ajax example and the non-ajax example) can be combined when necessary. For instance, if we take getStuff from the ajax example and we decide we have to do some processing on the data before we hand it off to getMoreStuff, we'd change it like this: Fiddle

function getStuff() {
    // Create our own Deferred
    var d = new $.Deferred();
    display("getStuff starting ajax")
    $.ajax({
        url: "/echo/json/",
        type: "POST",
        data: {json: '{"message": "data from first request"}', delay: 1},
        dataType: "json",
        success: function(data) {
            // Modify the data
            data.message = "MODIFIED " + data.message;

            // Resolve with the modified data
            d.resolve(data);
        }
    });
    return d;
}

请注意,我们如何使用这些并没有改变:

Note that how we use that didn't change:

getStuff().then(getMoreStuff).then(doSomethingWithStuff);

所有这些改变是在 getStuff

这是对整个承诺概念的伟大的事情之一(这是不是在所有具体到jQuery的,但jQuery的为我们提供了方便的版本使用),它是梦幻般的去耦的事情。

This is one of the great things about the whole "promise" concept (which isn't at all specific to jQuery, but jQuery gives us handy versions to use), it's fantastic for decoupling things.

这篇关于如何避免硬codeD,在Javascript / jQuery的链式异步函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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