English 中文(简体)
我怎么回过声回击?
原标题:How do I return the response from an asynchronous call?

我怎么回去回应/来自要求破灭的<条码>。

I am trying to return the value from the callback, as well as assigning the result to a local variable inside the function and returning that one, but none of those ways actually return the response — they all return undefined or whatever the initial value of the variable result is.

www.un.org/Depts/DGACM/index_spanish.htm 接受电话的同步功能实例 (使用j Query s ajax功能):

function foo() {
    var result;

    $.ajax({
        url:  ... ,
        success: function(response) {
            result = response;
            // return response; // <- I tried that one as well
        }
    });

    return result; // It always returns `undefined`
}

<>Example using Node.js:

function foo() {
    var result;

    fs.readFile("path/to/file", function(err, data) {
        result = data;
        // return data; // <- I tried that one as well
    });

    return result; // It always returns `undefined`
}

www.un.org/Depts/DGACM/index_spanish.htm 承诺的选编:

function foo() {
    var result;

    fetch(url).then(function(response) {
        result = response;
        // return response; // <- I tried that one as well
    });

    return result; // It always returns `undefined`
}
最佳回答

关于不同例子的超常行为的解释,见。 我为什么在一个职能范围内加以修改后,我的变数没有改变? - 《民法》参考资料

如果你已经理解这一问题,就能够找到以下可能的解决办法:。

The problem

<>A,Ajax > 代表synchronous 。 这意味着将请求(或接受答复)放在正常执行流动之外。 举例来说,$.ajax Return Immediate and the next statement,return results;, is implementing before the function sent as success, callsback was Even calls.

这里是一种类似做法,希望能够使同步流动和同步流动之间的区别更加明确:

Synchronous

请你打电话给朋友,请他找你。 虽然这可能会有一段时期,但你在等待电话和星号进入空间,直到你的朋友给你必要的答案。

当你履行包含“正常”法典的职能时,情况也是如此:

function findItem() {
    var item;
    while(item_not_found) {
        // search
    }
    return item;
}

var item = findItem();

// Do something with item
doSomethingElse();

即便是find 项目可能需要很长时间才能执行,任何在<条码>后加入的代码:wait,直至该功能恢复。

Asynchronous

出于同样的原因,你再次请你的朋友发言。 但此时,你告诉他,你正在忙之中,他应该在你的移动电话上打回<>。 你hang,离开房屋,尽一切计划做事。 一旦你的朋友打电话给你,你将处理他给你的信息。

这正是你在阿贾克斯提出请求时发生的事情。

findItem(function(item) {
    // Do something with the item
});
doSomethingElse();

处决不是等待答复,而是立即继续进行,Ajax呼吁之后的陈述得到执行。 为了最终做出回应,你提供了一旦收到答复即称为“召回<>>/em”的职能(注意到什么? ? 发出这一呼吁之后提出的任何声明均在发出呼吁之前执行。


Solution(s)

www.un.org/Depts/DGACM/index_spanish.htm Embrace the asynchronous nature ofgust Java! 虽然某些同步作业提供了同步的对应单位(也提供“Ajax”),但通常会阻止使用,特别是在浏览器的情况下。

你们为什么不问?

贾瓦文位于浏览器的电离层,任何长期过程都将锁定电离层,使其无法应对。 此外,对贾瓦文的执行时间有上限,浏览器将询问用户是否继续执行。

All of this results in a really bad user experience. The user won t be able to tell whether everything is working fine or not. Furthermore, the effect will be worse for users with a slow connection.

In the following we will look at three different solutions that are all building on top of each other:

  • Promises with async/await (ES2017+, available in older browsers if you use a transpiler or regenerator)
  • Callbacks (popular in node)
  • Promises with then() (ES2015+, available in older browsers if you use one of the many promise libraries)

www.un.org/Depts/DGACM/index_spanish.htm 现有浏览器和第7+号:。


ES2017+: Promises with async/await

2017年发表的《欧洲海事委员会章程》介绍了 为履行同步职能而提供的支持<>。 在<代码>sync和await的帮助下,你可以在“同步风格”中写成“同步”。 法典仍然很不成熟,但更容易读/理解。

www.un.org/Depts/DGACM/index_spanish.htm 在承诺的基础上再接再厉:<条码>sync的功能始终回报承诺:<条码>await<>>>>>>>“不校正”许诺,或者导致承诺的价值在承诺被拒时得到解决或留下错误。

<>Important: 您只能使用<代码>await在<条码>内或https://developer.mozilla.org/en-US/docs/Web/Java/Guide/Modules” rel=“noreferer”栏内。 顶级<代码>await 模块外没有支持,因此,你可能不得不做一个综合二FE(。 立即生效:<>条码>。 如果不使用模块,情况如何。

https://developer.mozilla.org/en-US/docs/Web/Javagust/Reference/Statements/async_Function”rel=“noretinger”>async/><<<>>><<><>>>>><<>>><>>>>>a>。

Here is an example that elaborates the delay function findItem() above:

// Using  superagent  which will return a promise.
var superagent = require( superagent )

// This is isn t declared as `async` because it already returns a promise
function delay() {
  // `delay` returns a promise
  return new Promise(function(resolve, reject) {
    // Only `delay` is able to resolve or reject the promise
    setTimeout(function() {
      resolve(42); // After 3 seconds, resolve the promise with value 42
    }, 3000);
  });
}

async function getAllBooks() {
  try {
    // GET a list of book IDs of the current user
    var bookIDs = await superagent.get( /user/books );
    // wait for 3 seconds (just for the sake of this example)
    await delay();
    // GET information about each book
    return superagent.get( /books/ids= +JSON.stringify(bookIDs));
  } catch(error) {
    // If any of the awaited promises was rejected, this catch block
    // would catch the rejection reason
    return null;
  }
}

// Start an IIFE to use `await` at the top level
(async function(){
  let books = await getAllBooks();
  console.log(books);
})();

Current browser async/await。 在regenerator的帮助下,你还可以支持旧的环境。 (或使用再生器的工具,例如Babel。)


Let functions accept callbacks

退约是指职能1转为职能时。 2. 职能2可随时随行1。 在一个同步的进程中,只要完成同步进程,就会叫退。 通常,结果会反馈。

在问题的例子中,你可以提出<条码>foo接受退约,并将其作为<条码>。 因此,

var result = foo();
// Code that depends on  result 

......

foo(function(result) {
    // Code that depends on  result 
});

我们在此界定了“在线”职能,但你可以通过任何职能参考:

function myCallback(result) {
    // Code that depends on  result 
}

foo(myCallback);

定义如下:

function foo(callback) {
    $.ajax({
        // ...
        success: callback
    });
}

。 当我们称之为“标准/编码”时,我们将其通过。 一、Ajax申请一经成功,$.ajax将打电话到 查询<>/code>,并通过对反馈的答复(可参见result,因为这正是我们如何界定反馈。

你们也可以处理对策,然后把对策传回:

function foo(callback) {
    $.ajax({
        // ...
        success: function(response) {
            // For example, filter the response
            callback(filtered_response);
        }
    });
}

It s easier to write code using callbacks than it may seem. After all, JavaScript in the browser is heavily event-driven (DOM events). Receiving the Ajax response is nothing else but an event. Difficulties could arise when you have to work with third-party code, but most problems can be solved by just thinking through the application flow.


ES2015+: Promises with then()

The Promise API is a new feature of ECMAScript 6 (ES2015), but it has good browser support already. There are also many libraries which implement the standard Promises API and provide additional methods to ease the use and composition of asynchronous functions (e.g., bluebird).

通行证是future值的集装箱。 如果承诺得到价值(即resolved)或取消价值(rejected),则通知所有希望获得这一价值的“列入名单者”。

The advantage over plain callbacks is that they allow you to decouple your code and they are easier to compose.

这里是利用承诺的一个例子:

function delay() {
  // `delay` returns a promise
  return new Promise(function(resolve, reject) {
    // Only `delay` is able to resolve or reject the promise
    setTimeout(function() {
      resolve(42); // After 3 seconds, resolve the promise with value 42
    }, 3000);
  });
}

delay()
  .then(function(v) { // `delay` returns a promise
    console.log(v); // Log the value once it is resolved
  })
  .catch(function(v) {
    // Or do something else if it is rejected
    // (it would not happen in this example, since `reject` is not called).
  });
.as-console-wrapper { max-height: 100% !important; top: 0; }

Applied to our Ajax call we could use promises like this:

function ajax(url) {
  return new Promise(function(resolve, reject) {
    var xhr = new XMLHttpRequest();
    xhr.onload = function() {
      resolve(this.responseText);
    };
    xhr.onerror = reject;
    xhr.open( GET , url);
    xhr.send();
  });
}

ajax("https://jsonplaceholder.typicode.com/todos/1")
  .then(function(result) {
    console.log(result); // Code depending on result
  })
  .catch(function() {
    // An error occurred
  });
.as-console-wrapper { max-height: 100% !important; top: 0; }

阐述允诺提供的所有好处不属于本答复的范围,但如果你撰写新的法典,你应认真考虑这些好处。 它们为你的法典提供了很大的抽象和分离。

More information about promises: HTML5 rocks - JavaScript Promises.

Side note: jQuery s deferred objects

递延物体是指 j履行承诺的习惯(在产品预报标准化之前)。 他们几乎像承诺一样行事,但暴露了一种稍有不同的趋势。

Every Ajax method of jQuery already returns a "deferred object" (actually a promise of a deferred object) which you can just return from your function:

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

ajax().done(function(result) {
    // Code depending on result
}).fail(function() {
    // An error occurred
});

Side note: Promise gotchas

考虑到未来价值的承诺和推迟目标只是containers,它们不是价值本身。 例如,你有:

function checkPassword() {
    return $.ajax({
        url:  /password ,
        data: {
            username: $( #username ).val(),
            password: $( #password ).val()
        },
        type:  POST ,
        dataType:  json 
    });
}

if (checkPassword()) {
    // Tell the user they re logged in
}

This code misunderstands the above asynchronous issues. Specifically, $.ajax() doesn t freeze the code while it checks the /password page on your server - it sends a request to the server and while it waits, it immediately returns a jQuery Ajax Deferred object, not the response from the server. That means the if statement is going to always get this Deferred object, treat it as true, and proceed as though the user is logged in. Not good.

但是,固定办法很容易:

checkPassword()
.done(function(r) {
    if (r) {
        // Tell the user they re logged in
    } else {
        // Tell the user their password was bad
    }
})
.fail(function(x) {
    // Tell the user something bad happened
});

Not recommended: Synchronous "Ajax" calls

As I mentioned, some(!) asynchronous operations have synchronous counterparts. I don t advocate their use, but for completeness sake, here is how you would perform a synchronous call:

Without jQuery

If you directly use a XMLHttpRequest object, pass false as third argument to .open.

jQuery

If you use jQuery, you can set the async option to false. Note that this option is deprecated since jQuery 1.8. You can then either still use a success callback or access the responseText property of the jqXHR object:

function foo() {
    var jqXHR = $.ajax({
        //...
        async: false
    });
    return jqXHR.responseText;
}

如果您使用任何其他j Query Ajax方法,例如$.get,$.getJSON/code>,你必须将其改为$.ajax。 (因为你只能将配置参数通过<代码>。

Heads up! It is not possible to make a synchronous JSONP request. JSONP by its very nature is always asynchronous (one more reason to not even consider this option).

问题回答

If you re not using jQuery in your code, this answer is for you

Your code should be something along the lines of this:

function foo() {
    var httpRequest = new XMLHttpRequest();
    httpRequest.open( GET , "/echo/json");
    httpRequest.send();
    return httpRequest.responseText;
}

var result = foo(); // Always ends up being  undefined 

Kling公司做了一项细微的工作 ,为AJAX使用jQuery的人写了答案,但我已决定为持单人提供一种选择。

(fetch的用户说明 页: 1


What you re facing

如果你在阅读后不相信“问题解释”的话,这是另一个答案的简短摘要。

The A in AJAX is for asynchronous. 这意味着将请求(或接受答复)放在正常执行流动之外。 在你的例子中,.send 立即返回和下一份声明return results;,甚至在通过<编码><时执行。

这意味着,在你回来时,被定义的听众尚未执行,这意味着你重新返回的价值尚未确定。

这里是简单的类比:

function getFive(){
    var a;
    setTimeout(function(){
         a=5;
    },10);
    return a;
}

<代码>a 退回的数值为un defined。 自a=5以来 部分尚未执行。 几内亚和日本宇宙航空研究开发机构也这样做,在服务器有机会告诉你的浏览器这一价值之前,你将重新估价。

解决这一问题的一个可能办法是将-actively编码,说明在计算完成后,你的方案要做什么。

function onComplete(a){ // When the code completes, do this
    alert(a);
}

function getFive(whenDone){
    var a;
    setTimeout(function(){
         a=5;
         whenDone(a);
    },10);
}

http://en.wikipedia.org/wiki/Continuation-passing_type”rel=“noretinger”>CPS。 基本上,我们通过<条码>植被指数/代码>,在完成后采取行动,我们重新告诉我们的代码,在事件结束时如何作出反应(如我们的非洲宇宙航空研究开发机构呼吁,或在此情况下是时间)。

使用:

getFive(onComplete);

http://jsfiddle.net/PAjZR/“rel=“noretinger”>(Fiddle)。

Possible solutions

基本上有两种办法可以解决这个问题:

  1. Make the AJAX call synchronous (let’s call it SJAX).
  2. Restructure your code to work properly with callbacks.

1. Synchronous AJAX - Don t do it!!

nch,don t do it! 费利克斯的回答使人对它为什么产生坏的想法提出令人信服的论点。 总而言之,它冻结了用户浏览器,直到服务器回复,并造成用户经验非常坏。 下面是国际发展部关于以下原因的简短摘要:

XMLHttpRequest supports both synchronous and asynchronous communications. In general, however, asynchronous requests should be preferred to synchronous requests for performance reasons.

简言之,仓促要求阻止执行法典...... ......这可能造成严重问题......

如果你(<>have/em>,你可以通过国旗。 以下是:

var request = new XMLHttpRequest();
request.open( GET ,  yourURL , false);  // `false` makes the request synchronous
request.send(null);

if (request.status === 200) {// That s HTTP for  ok 
  console.log(request.responseText);
}

2. Restructure code

让我们的工作受到挫折。 举例而言,可采用<代码>foo接受退约。 在<代码>foo上填满时,我们要告诉我们的代码。

因此:

var result = foo();
// Code that depends on `result` goes here

Becomes:

foo(function(result) {
    // Code that depends on `result`
});

在这里,我们通过匿名职能,但我们同样可以很容易地提及现有职能,这样我们就看:

function myHandler(result) {
    // Code that depends on `result`
}
foo(myHandler);

对于如何进行这种反馈设计的更多细节,检查费利克斯的回答。

现在,让我们界定禁忌,以便采取相应的行动。

function foo(callback) {
    var httpRequest = new XMLHttpRequest();
    httpRequest.onload = function(){ // When the request is loaded
       callback(httpRequest.responseText);// We re calling our method
    };
    httpRequest.open( GET , "/echo/json");
    httpRequest.send();
}

我们现在已经把我们的“foo>功能接受一项行动,以便在非洲宇宙航空研究开发机构成功完成时运行。 我们可以进一步扩大这一范围,办法是检查反应状况是否为200,并相应采取行动(造成一个失败的手和这样的人)。 有效地解决了我们的问题。

If you re still having a hard time understanding this, read the AJAX getting started guide at MDN.

<http://en.wikipedia.org/wiki/XMLHttpRequest”rel=“noreferer”> XMLHttpRequest 2(首先,阅读了Benjamin Gruenbaum

如果你不使用 j,想要一个在现代浏览器和流动浏览器中工作的短 XXMLHttpRequest 2,我建议采用这一方式:

function ajax(a, b, c){ // URL, callback, just a placeholder
  c = new XMLHttpRequest;
  c.open( GET , a);
  c.onload = b;
  c.send()
}

你们可以看到:

  1. It s shorter than all other functions Listed.
  2. The callback is set directly (so no extra unnecessary closures).
  3. It uses the new onload (so you don t have to check for readystate && status)
  4. There are some other situations, which I don t remember, that make the XMLHttpRequest 1 annoying.

有了两种办法,才能得到这一阿贾克斯呼吁的响应(三个采用XMLHttpRequest var名称):

最简单:

this.response

或者,如果出于某种原因,请见bind(>>,请示某类:

e.target.response

例:

function callback(e){
  console.log(this.response);
}
ajax( URL , callback);

或者(以上是更名人的职能,总是问题):

ajax( URL , function(e){console.log(this.response)});

任何事情都不容易。

现在,有些人可能说,最好使用read变或甚至XMLHttpRequest变称。 这是错误的。

XMLHttpRequest高级特征

它支持所有现代浏览器。 我可以确认,自创立XMLHttpRequest 2以来,我一直采用这种做法。 在我使用的任何浏览器中,我从未有过任何类型的问题。

只有在你希望把头脑带上2个州时,才进行渗透。

使用<代码>XMLHttpRequest的可变名称是另一大错误,因为你需要在上载/翻新状态关闭内进行回击,否则就失去了。


现在,如果你想使用POST和表格Data,你可以轻松地扩展这一功能:

function x(a, b, e, d, c){ // URL, callback, method, formdata or {key:val},placeholder
  c = new XMLHttpRequest;
  c.open(e|| get , a);
  c.onload = b;
  c.send(d||null)
}

它又发挥了非常简短的职能,但它确实是GET 和POST。

使用实例:

x(url, callback); // By default it s GET so no need to set
x(url, callback,  post , { key :  val }); // No need to set POST data

或者通过完整的形式要素(document.getElementsByTagName(表格)[0]):

var fd = new FormData(form);
x(url, callback,  post , fd);

或者确定一些习俗价值:

var fd = new FormData();
fd.append( key ,  val )
x(url, callback,  post , fd);

如你所知,我没有执行yn,......这是一件坏事。

说了这......为什么我们不易做吗?


正如评论中所提到的,使用错误和复制;同步,完全打破了答案。 以适当方式使用Ajax是一种极短的途径?

function x(a, b, e, d, c){ // URL, callback, method, formdata or {key:val}, placeholder
  c = new XMLHttpRequest;
  c.open(e|| get , a);
  c.onload = b;
  c.onerror = error;
  c.send(d||null)
}

function error(e){
  console.log( --Error-- , this.type);
  console.log( this:  , this);
  console.log( Event:  , e)
}
function displayAjax(e){
  console.log(e, this);
}
x( WRONGURL , displayAjax);

在上述文字中,你有一个错误的手稿,固定定义,因此不会损害这一功能。 错误手稿也可用于其他功能。

但是,为了真正消除错误,只有 方式是写出错误的URL,在这种情况下,每名浏览器都会犯错。

Error handlers are maybe useful if you set custom headers, set the responseType to blob array buffer, or whatever...

Even if you pass POSTAPAPAP as the method it won t throw an error.

即便你将fdggdgilfdghfldj作为数据形式,也赢得了一滴错误。

In the first case the error is inside the displayAjax() under this.statusText as Method not Allowed.

In the second case, it simply works. You have to check at the server side if you passed the right post data.

交叉主人不得自动犯错。

在对错误的答复中,没有任何错误代码。

仅限<条码>。

Why add an error handler if you totally don t have any control over errors? Most of the errors are returned inside this in the callback function displayAjax().

So: There isn t any need for error checks if you re able to copy and paste the URL properly. ;)

PS:第一次测试是x(x ,显示Ajax)的,完全是反应吗? 因此,我检查了超文本的夹,并有一个称为X.xml的档案。 因此,即使你忘记延长你的档案XMLHttpRequest 2 WILL FIND IT。 页: 1


Read a file synchronous

www.un.org/Depts/DGACM/index_spanish.htm Don t do that

如果你想把浏览器捆绑起来,同时装上一只冰大码

function omg(a, c){ // URL
  c = new XMLHttpRequest;
  c.open( GET , a, true);
  c.send();
  return c; // Or c.response
}

Now you can do

 var res = omg( thisIsGonnaBlockThePage.txt );

There is no other way to do this in a non-asynchronous way. (Yeah, with setTimeout loop... but seriously?)

另一点是...... 如果你与Alfonso公司合作,或只是你自己的名单,或你总是对每一项请求使用不同功能......

只有在你有一页时,你才总装上XML/JIN,或者你只需要一个功能。 在这种情况下,只修改Ajax功能,用你的特殊职能取代b。


上述职能用于基本用途。

如果您希望extend 职能......

是的,你可以。

I m使用大量APIC和第一个功能之一,我融入每个超文本页面是本答复中第一个Ajax功能,只有GET。

但是,你可以做许多与XMLHttpRequest:

我担任了下载主管(在双方使用范围,恢复、存档、档案系统)、各种图像变压器转换器,使用信封,使用基64images的居民区网络数据库,以及更多......)

但是,在这种情况下,你只能为此目的创造一种功能......有时需要一种博览、阵列缓冲,你可以树立头盔,压倒性奇像,而且还有许多东西......

但这里的问题是,如何回复阿贾克斯岛的对策。 (我增加了一条容易的方式。)

If you re using promises, this answer is for you.

XHRs顶替(fetch),,

你们的法典应当符合以下原则:

function foo() {
    var data;
    // Or $.get(...).then, or request(...).then, or query(...).then
    fetch("/echo/json").then(function(response){
        data = response.json();
    });
    return data;
}

var result = foo(); //  result  is always undefined no matter what.

Kling公司做了一项细微的工作,为Ajax使用 j门的人写了答案。 我对本土的XHR做了回答。 答案是在前线或后方普遍使用承诺。


The core issue

浏览器和诺德.js/io.js的服务器上的Java文本一致模式是asynchronousreactive

每当你称之为回报一种承诺的方法时,then的操作者为always,按时间顺序执行,即 subsequently/strong> 载于<代码>then的手稿。

This means when you re returning data the then handler you ve defined did not execute yet. This in turn means that the value you re returning has not been set to the correct value in time.

Here is a simple analogy for the issue:

    function getFive(){
        var data;
        setTimeout(function(){ // Set a timer for one second in the future
           data = 5; // After a second, do this
        }, 1000);
        return data;
    }
    document.body.innerHTML = getFive(); // `undefined` here and not 5

。 自<代码>数据=5部分尚未执行。 它可能第二次执行,但到那时它与返还价值无关。

由于这项行动尚未发生(Ajax,服务器电话,I/O和时间r),你在请求获得机会告诉你的代码这一价值之前,重新回到了价值。

One possible solution to this problem is to code re-actively, telling your program what to do when the calculation completed. Promises actively enable this by being temporal (time-sensitive) in nature.

Quick recap on promises

时间:价值 许可权已经生效。 他们开始没有价值,可以解决:

  • fulfilled meaning that the computation completed successfully.
  • rejected meaning that the computation failed.

允诺只能更改国家once,此后将永远在同一州停留。 您可附上<代码>then,操作员承诺提取价值和处理错误。 chaining。 房地由或j Query s $.get/code>回报许诺。

当我们打电话,then on a pledges and return 我们从中获得了加工值的承诺。 如果我们再回另一个承诺,我们就会激动人心,但让我们hor。

With promises

让我们看看我们如何能够以承诺解决上述问题。 首先,请通过利用Promise Constructionor,表明我们对上述承诺国的理解,以建立延迟职能:

function delay(ms){ // Takes amount of milliseconds
    // Returns a new promise
    return new Promise(function(resolve, reject){
        setTimeout(function(){ // When the time is up,
            resolve(); // change the promise to the fulfilled state
        }, ms);
    });
}

现在,在我们,将其计算成:

function delay(ms){ // Takes amount of milliseconds
  // Returns a new promise
  return new Promise(function(resolve, reject){
    setTimeout(function(){ // When the time is up,
      resolve(); // change the promise to the fulfilled state
    }, ms);
  });
}

function getFive(){
  // We re RETURNING the promise. Remember, a promise is a wrapper over our value
  return delay(100).then(function(){ // When the promise is ready,
      return 5; // return the value 5. Promises are all about return values
  })
}
// We _have_ to wrap it like this in the call site, and we can t access the plain value
getFive().then(function(five){
   document.body.innerHTML = five;
});

基本上,我们不恢复“ 珍/em>,而由于赞同模式,我们可以做些什么? 它像你可以打开一个盒子,then

Applying this

您的原计划呼吁也是如此。

function foo() {
    // RETURN the promise
    return fetch("/echo/json").then(function(response){
        return response.json(); // Process it inside the `then`
    });
}

foo().then(function(response){
    // Access the value inside the `then`
})

因此,这项工作也是一样的。 我们学到的教训是,我们能够从已经不成熟的电话中收回价值,但我们能够利用承诺,并引导它们进行加工。 我们现在知道,如何以一致的呼声来回复。

ES2015 (ES6)

ES6 介绍

function* foo(){ // Notice the star. This is ES6, so new browsers, Nodes.js, and io.js only
    yield 1;
    yield 2;
    while(true) yield 3;
}

Is a function that returns an iterator over the sequence 1,2,3,3,3,3,.... which can be iterated. While this is interesting on its own and opens room for a lot of possibility, there is one particular interesting case.

如果我们重新产生的顺序是一系列行动而不是数量,那么我们就可以在行动产生时放弃这一职能,等待我们恢复这一职能。 因此,我们需要的不是一系列数字,而是一系列的future<>>/em>价值——即:许诺。

这只是一种trick笑,但很强的骗子,让我们以同步的方式撰写非同步的法典。 有几个“管理者”对你们来说就是这样。 写作是几行法典,但超出了这一答案的范围。 I ll are used Blue鸟类 scode>Promise.coroutine here, but there are other summarypers such as co or Q.async.

var foo = coroutine(function*(){
    var data = yield fetch("/echo/json"); // Notice the yield
    // The code here only executes _after_ the request is done
    return data.json(); //  data  is defined
});

这种方法回馈了承诺,我们可以从其他公司消费。 例如:

var main = coroutine(function*(){
   var bar = yield foo(); // Wait our earlier coroutine. It returns a promise
   // The server call is done here, and the code below executes when done
   var baz = yield fetch("/api/users/" + bar.userid); // Depends on foo s result
   console.log(baz); // Runs after both requests are done
});
main();

ES2016 (ES7)

在ES7中,这进一步标准化。 现在有几项建议,但在所有建议中,你都可以在<代码>await许诺。 这只是上文ES6提案的“超级车”(nic),增加了<条码>sync和<代码>await的关键词。 举上述例子:

async function foo(){
    var data = await fetch("/echo/json"); // Notice the await
    // code here only executes _after_ the request is done
    return data.json(); //  data  is defined
}

它仍然只是希望:

你使用Ajax是不正确的。 想法不是让它归还任何东西,而是把数据交给一个处理数据问题的警示职能。

That is:

function handleData( responseData ) {

    // Do what you want with the data
    console.log(responseData);
}

$.ajax({
    url: "hi.php",
    ...
    success: function ( data, status, XHR ) {
        handleData(data);
    }
});

交出手里的任何事情都不会发生。 否则,你要么放弃数据,要么直接在成功职能范围内做你想要的。

The simplest solution is to create a JavaScript function and call it for the Ajax success callback.

function callServerAsync(){
    $.ajax({
        url:  ... ,
        success: function(response) {

            successCallback(response);
        }
    });
}

function successCallback(responseObj){
    // Do something like read the response and show data
    alert(JSON.stringify(responseObj)); // Only applicable to a JSON response
}

function foo(callback) {

    $.ajax({
        url:  ... ,
        success: function(response) {
           return callback(null, response);
        }
    });
}

var result = foo(function(err, result){
          if (!err)
           console.log(result);
});

这里的大多数答复都对你开展单一合成行动提供了有益的建议,但有时,当你需要为每个进入一个阵列或其他类似名单的结构进行同步运作时,就会出现这种情况。 这样做的诱惑是:

// WRONG
var results = [];
theArray.forEach(function(entry) {
    doSomethingAsync(entry, function(result) {
        results.push(result);
    });
});
console.log(results); // E.g., using them, returning them, etc.

例:

// WRONG
var theArray = [1, 2, 3];
var results = [];
theArray.forEach(function(entry) {
    doSomethingAsync(entry, function(result) {
        results.push(result);
    });
});
console.log("Results:", results); // E.g., using them, returning them, etc.

function doSomethingAsync(value, callback) {
    console.log("Starting async operation for " + value);
    setTimeout(function() {
        console.log("Completing async operation for " + value);
        callback(value * 2);
    }, Math.floor(Math.random() * 200));
}
.as-console-wrapper { max-height: 100% !important; }

工作滞后的原因是,到你再次尝试利用结果时为止,从doSomethingAsync上调回的警示。

So, if you have an array (or list of some kind) and want to do async operations for each entry, you have two options: Do the operations in parallel (overlapping), or in series (one after another in sequence).

Parallel

你们可以开始所有这些工作,随时了解你们期望的多少次反馈,然后在你发出警告时利用成果:

var results = [];
var expecting = theArray.length;
theArray.forEach(function(entry, index) {
    doSomethingAsync(entry, function(result) {
        results[index] = result;
        if (--expecting === 0) {
            // Done!
            console.log("Results:", results); // E.g., using the results
        }
    });
});

例:

var theArray = [1, 2, 3];
var results = [];
var expecting = theArray.length;
theArray.forEach(function(entry, index) {
    doSomethingAsync(entry, function(result) {
        results[index] = result;
        if (--expecting === 0) {
            // Done!
            console.log("Results:", JSON.stringify(results)); // E.g., using the results
        }
    });
});

function doSomethingAsync(value, callback) {
    console.log("Starting async operation for " + value);
    setTimeout(function() {
        console.log("Completing async operation for " + value);
        callback(value * 2);
    }, Math.floor(Math.random() * 200));
}
.as-console-wrapper { max-height: 100% !important; }

(我们可以取消<>Expecting,并仅使用results.length=Array.length,但让我们可以选择:the Array在电话尚未发出时改动。

Notice how we use the index from forEach to save the result in results in the same position as the entry it relates to, even if the results arrive out of order (since async calls don t necessarily complete in the order in which they were started).

But what if you need to return those results from a function? As the other answers have pointed out, you can t; you have to have your function accept and call a callback (or return a Promise). Here s a callback version:

function doSomethingWith(theArray, callback) {
    var results = [];
    var expecting = theArray.length;
    theArray.forEach(function(entry, index) {
        doSomethingAsync(entry, function(result) {
            results[index] = result;
            if (--expecting === 0) {
                // Done!
                callback(results);
            }
        });
    });
}
doSomethingWith(theArray, function(results) {
    console.log("Results:", results);
});

例:

function doSomethingWith(theArray, callback) {
    var results = [];
    var expecting = theArray.length;
    theArray.forEach(function(entry, index) {
        doSomethingAsync(entry, function(result) {
            results[index] = result;
            if (--expecting === 0) {
                // Done!
                callback(results);
            }
        });
    });
}
doSomethingWith([1, 2, 3], function(results) {
    console.log("Results:", JSON.stringify(results));
});

function doSomethingAsync(value, callback) {
    console.log("Starting async operation for " + value);
    setTimeout(function() {
        console.log("Completing async operation for " + value);
        callback(value * 2);
    }, Math.floor(Math.random() * 200));
}
.as-console-wrapper { max-height: 100% !important; }

Or here s a version returning a Promise instead:

function doSomethingWith(theArray) {
    return new Promise(function(resolve) {
        var results = [];
        var expecting = theArray.length;
        theArray.forEach(function(entry, index) {
            doSomethingAsync(entry, function(result) {
                results[index] = result;
                if (--expecting === 0) {
                    // Done!
                    resolve(results);
                }
            });
        });
    });
}
doSomethingWith(theArray).then(function(results) {
    console.log("Results:", results);
});

Of course,如果doSomethingAsync通过错误,我们就使用reject<>code>,在我们发现错误时拒绝允诺。

例:

function doSomethingWith(theArray) {
    return new Promise(function(resolve) {
        var results = [];
        var expecting = theArray.length;
        theArray.forEach(function(entry, index) {
            doSomethingAsync(entry, function(result) {
                results[index] = result;
                if (--expecting === 0) {
                    // Done!
                    resolve(results);
                }
            });
        });
    });
}
doSomethingWith([1, 2, 3]).then(function(results) {
    console.log("Results:", JSON.stringify(results));
});

function doSomethingAsync(value, callback) {
    console.log("Starting async operation for " + value);
    setTimeout(function() {
        console.log("Completing async operation for " + value);
        callback(value * 2);
    }, Math.floor(Math.random() * 200));
}
.as-console-wrapper { max-height: 100% !important; }

(轮流担任,请在<条码>上填写,以兑现承诺,然后填写<>。

Promise

function doSomethingWith(theArray) {
    return Promise.all(theArray.map(function(entry) {
        return doSomethingAsync(entry);
    }));
}
doSomethingWith(theArray).then(function(results) {
    console.log("Results:", results);
});

If you know that doSomethingAsync will ignore a second and third argument, you can just pass it directly to map (map calls its callback with three arguments, but most people only use the first most of the time):

function doSomethingWith(theArray) {
    return Promise.all(theArray.map(doSomethingAsync));
}
doSomethingWith(theArray).then(function(results) {
    console.log("Results:", results);
});

例:

function doSomethingWith(theArray) {
    return Promise.all(theArray.map(doSomethingAsync));
}
doSomethingWith([1, 2, 3]).then(function(results) {
    console.log("Results:", JSON.stringify(results));
});

function doSomethingAsync(value) {
    console.log("Starting async operation for " + value);
    return new Promise(function(resolve) {
        setTimeout(function() {
            console.log("Completing async operation for " + value);
            resolve(value * 2);
        }, Math.floor(Math.random() * 200));
    });
}
.as-console-wrapper { max-height: 100% !important; }

请注意,Promise.all在你所承诺的第1时,以你所给予的所有承诺的一系列结果兑现其诺言,或者在你所拒绝的承诺的第1时拒绝这一承诺。

Series

你们不希望同时开展行动? 如果你想接手,你需要等到每次行动之后才能结束。 这里是发挥这一作用的一个实例,因此呼吁:

function doSomethingWith(theArray, callback) {
    var results = [];
    doOne(0);
    function doOne(index) {
        if (index < theArray.length) {
            doSomethingAsync(theArray[index], function(result) {
                results.push(result);
                doOne(index + 1);
            });
        } else {
            // Done!
            callback(results);
        }
    }
}
doSomethingWith(theArray, function(results) {
    console.log("Results:", results);
});

(如果我们重新开展一系列工作,我们就只能使用<条码>results.push(result),因为我们知道我们没有取得结果。 在上述几个例子中,我们可以使用<代码>results[index] = 结果;,但我们没有使用索引。

例:

function doSomethingWith(theArray, callback) {
    var results = [];
    doOne(0);
    function doOne(index) {
        if (index < theArray.length) {
            doSomethingAsync(theArray[index], function(result) {
                results.push(result);
                doOne(index + 1);
            });
        } else {
            // Done!
            callback(results);
        }
    }
}
doSomethingWith([1, 2, 3], function(results) {
    console.log("Results:", JSON.stringify(results));
});

function doSomethingAsync(value, callback) {
    console.log("Starting async operation for " + value);
    setTimeout(function() {
        console.log("Completing async operation for " + value);
        callback(value * 2);
    }, Math.floor(Math.random() * 200));
}
.as-console-wrapper { max-height: 100% !important; }

(Or, 再次为doSomethingAsync制作一个包裹,使您有希望,并做以下工作:

http://www.un.org

async function doSomethingWith(theArray) {
    const results = [];
    for (const entry of theArray) {
        results.push(await doSomethingAsync(entry));
    }
    return results;
}
doSomethingWith(theArray).then(results => {
    console.log("Results:", results);
});

例:

async function doSomethingWith(theArray) {
    const results = [];
    for (const entry of theArray) {
        results.push(await doSomethingAsync(entry));
    }
    return results;
}
doSomethingWith([1, 2, 3]).then(function(results) {
    console.log("Results:", JSON.stringify(results));
});

function doSomethingAsync(value) {
    console.log("Starting async operation for " + value);
    return new Promise(function(resolve) {
        setTimeout(function() {
            console.log("Completing async operation for " + value);
            resolve(value * 2);
        }, Math.floor(Math.random() * 200));
    });
}
.as-console-wrapper { max-height: 100% !important; }

如果你能够使用ES2017+ syntax(yet),你可以在上作一个改动。” 减少“模式 (由于我们不把结果从结果转过来,而是将成果汇集成阵列,因此,这比通常的明智做法更为复杂):

function doSomethingWith(theArray) {
    return theArray.reduce(function(p, entry) {
        return p.then(function(results) {
            return doSomethingAsync(entry).then(function(result) {
                results.push(result);
                return results;
            });
        });
    }, Promise.resolve([]));
}
doSomethingWith(theArray).then(function(results) {
    console.log("Results:", results);
});

例:

function doSomethingWith(theArray) {
    return theArray.reduce(function(p, entry) {
        return p.then(function(results) {
            return doSomethingAsync(entry).then(function(result) {
                results.push(result);
                return results;
            });
        });
    }, Promise.resolve([]));
}
doSomethingWith([1, 2, 3]).then(function(results) {
    console.log("Results:", JSON.stringify(results));
});

function doSomethingAsync(value) {
    console.log("Starting async operation for " + value);
    return new Promise(function(resolve) {
        setTimeout(function() {
            console.log("Completing async operation for " + value);
            resolve(value * 2);
        }, Math.floor(Math.random() * 200));
    });
}
.as-console-wrapper { max-height: 100% !important; }

......与

function doSomethingWith(theArray) {
    return theArray.reduce((p, entry) => p.then(results => doSomethingAsync(entry).then(result => {
        results.push(result);
        return results;
    })), Promise.resolve([]));
}
doSomethingWith(theArray).then(results => {
    console.log("Results:", results);
});

例:

function doSomethingWith(theArray) {
    return theArray.reduce((p, entry) => p.then(results => doSomethingAsync(entry).then(result => {
        results.push(result);
        return results;
    })), Promise.resolve([]));
}
doSomethingWith([1, 2, 3]).then(function(results) {
    console.log("Results:", JSON.stringify(results));
});

function doSomethingAsync(value) {
    console.log("Starting async operation for " + value);
    return new Promise(function(resolve) {
        setTimeout(function() {
            console.log("Completing async operation for " + value);
            resolve(value * 2);
        }, Math.floor(Math.random() * 200));
    });
}
.as-console-wrapper { max-height: 100% !important; }

它是一个非常常见的问题,我们在与 Java的神话作斗争时面临。 让我试图使今天的这种虚幻局面化为乌有。

让我们首先发挥简便的功能:

function foo(){
    // Do something
    return  wohoo ;
}

let bar = foo(); //  bar  is  wohoo  here

这是一项简单的同步职能要求(每条法典一行都按顺序完成,其结果与预期相同)。

Now let s add a bit of twist, by introducing a little delay in our function, so that all lines of code are not finished in sequence. Thus, it will emulate the asynchronous behavior of the function:

function foo(){
    setTimeout( ()=> {
        return  wohoo ;
   }, 1000)
}

let bar = foo() //  bar  is undefined here

因此,你们走了;这种拖延刚刚打破了我们所期望的功能! 但究竟发生了什么? 如果你看一下该守则,这实际上是合乎逻辑的。

The function foo(), upon execution, returns nothing (thus returned value is undefined), but it does start a timer, which executes a function after 1 second to return wohoo . But as you can see, the value that s assigned to bar is the immediately returned stuff from foo(), which is nothing, i.e., just undefined.

www.un.org/Depts/DGACM/index_spanish.htm 因此,我们如何处理这个问题?

Let s ask our function for a promise. Promise is really about what it means: it means that the function guarantees you to provide with any output it gets in future. So let s see it in action for our little problem above:

function foo(){
   return new Promise((resolve, reject) => { // I want foo() to PROMISE me something
    setTimeout ( function(){
      // Promise is RESOLVED, when the execution reaches this line of code
       resolve( wohoo ) // After 1 second, RESOLVE the promise with value  wohoo 
    }, 1000 )
  })
}

let bar;
foo().then( res => {
    bar = res;
    console.log(bar) // Will print  wohoo 
});

因此,摘要是——处理像阿贾克斯岛电话等同步功能,你可以使用<代码>resolve这一价值(你打算返回)的许诺。 因此,简而言之,你Resolve数值,而不是returning,以履行同步职能。

UPDATE (Promises with async/await)

Apart from using then/catch to work with promises, there exists one more approach. The idea is to recognize an asynchronous function and then wait for the promises to resolve, before moving to the next line of code. It s still just the promises under the hood, but with a different syntactical approach. To make things clearer, you can find a comparison below:

then/catch version:

function saveUsers(){
     getUsers()
      .then(users => {
         saveSomewhere(users);
      })
      .catch(err => {
          console.error(err);
       })
 }

async/await version:

  async function saveUsers(){
     try{
        let users = await getUsers()
        saveSomewhere(users);
     }
     catch(err){
        console.error(err);
     }
  }

另一种从轻度功能中收回价值的办法,是把这种结果储存在单一同步功能中。

Here is an example of the same:

var async = require("async");

// This wires up result back to the caller
var result = {};
var asyncTasks = [];
asyncTasks.push(function(_callback){
    // some asynchronous operation
    $.ajax({
        url:  ... ,
        success: function(response) {
            result.response = response;
            _callback();
        }
    });
});

async.parallel(asyncTasks, function(){
    // result is available after performing asynchronous operation
    console.log(result)
    console.log( Done );
});

I am using the result object to store the value during the asynchronous operation. This allows the result be available even after the asynchronous job.

我使用这种办法很多。 我很想知道,如果通过连续的模块把结果重新连接起来,这种做法如何奏效。

The following example I have written shows how to

这一工作实例是自成一体的。 它将界定一个简单的申请标语,使用窗户XMLHttpRequest,反对打电话。 它将确定一个简单的功能,以等待完成一系列承诺。

背景。 实例是查询,以便检索>>。 a. 特定组别的物体:

[
 "search?type=playlist&q=%22doom%20metal%22",
 "search?type=playlist&q=Adele"
]

对于每个项目,新的招标书将发射一个栏目——ExecutionBlock,按结果分类,根据结果阵列安排一套新的承诺,即:user/code>的物体清单,并在<>ExecutionProfileBlock内执行新的《吉大港河航道倡议》。

那么,你就可以看到一种宽松的假装结构,让你打上了多条、完全破灭的吉大港定居地,并通过<代码>Promise.all加入每一次电话的结果。

NOTE Recent Spotify search APIs will require an access token to be specified in the request headers:

-H "Authorization: Bearer {your access token}" 

因此,您举出以下例子:你需要把你接触到请求方中:

var spotifyAccessToken = "YourSpotifyAccessToken";
var console = {
    log: function(s) {
        document.getElementById("console").innerHTML += s + "<br/>"
    }
}

// Simple XMLHttpRequest
// based on https://davidwalsh.name/xmlhttprequest
SimpleRequest = {
    call: function(what, response) {
        var request;
        if (window.XMLHttpRequest) { // Mozilla, Safari, ...
            request = new XMLHttpRequest();
        } else if (window.ActiveXObject) { // Internet Explorer
            try {
                request = new ActiveXObject( Msxml2.XMLHTTP );
            }
            catch (e) {
                try {
                  request = new ActiveXObject( Microsoft.XMLHTTP );
                } catch (e) {}
            }
        }

        // State changes
        request.onreadystatechange = function() {
            if (request.readyState === 4) { // Done
                if (request.status === 200) { // Complete
                    response(request.responseText)
                }
                else
                    response();
            }
        }
        request.open( GET , what, true);
        request.setRequestHeader("Authorization", "Bearer " + spotifyAccessToken);
        request.send(null);
    }
}

//PromiseAll
var promiseAll = function(items, block, done, fail) {
    var self = this;
    var promises = [],
                   index = 0;
    items.forEach(function(item) {
        promises.push(function(item, i) {
            return new Promise(function(resolve, reject) {
                if (block) {
                    block.apply(this, [item, index, resolve, reject]);
                }
            });
        }(item, ++index))
    });
    Promise.all(promises).then(function AcceptHandler(results) {
        if (done) done(results);
    }, function ErrorHandler(error) {
        if (fail) fail(error);
    });
}; //promiseAll

// LP: deferred execution block
var ExecutionBlock = function(item, index, resolve, reject) {
    var url = "https://api.spotify.com/v1/"
    url += item;
    console.log( url )
    SimpleRequest.call(url, function(result) {
        if (result) {

            var profileUrls = JSON.parse(result).playlists.items.map(function(item, index) {
                return item.owner.href;
            })
            resolve(profileUrls);
        }
        else {
            reject(new Error("call error"));
        }
    })
}

arr = [
    "search?type=playlist&q=%22doom%20metal%22",
    "search?type=playlist&q=Adele"
]

promiseAll(arr, function(item, index, resolve, reject) {
    console.log("Making request [" + index + "]")
    ExecutionBlock(item, index, resolve, reject);
}, function(results) { // Aggregated results

    console.log("All profiles received " + results.length);
    //console.log(JSON.stringify(results[0], null, 2));

    ///// promiseall again

    var ExecutionProfileBlock = function(item, index, resolve, reject) {
        SimpleRequest.call(item, function(result) {
            if (result) {
                var obj = JSON.parse(result);
                resolve({
                    name: obj.display_name,
                    followers: obj.followers.total,
                    url: obj.href
                });
            } //result
        })
    } //ExecutionProfileBlock

    promiseAll(results[0], function(item, index, resolve, reject) {
        //console.log("Making request [" + index + "] " + item)
        ExecutionProfileBlock(item, index, resolve, reject);
    }, function(results) { // aggregated results
        console.log("All response received " + results.length);
        console.log(JSON.stringify(results, null, 2));
    }

    , function(error) { // Error
        console.log(error);
    })

    /////

  },
  function(error) { // Error
      console.log(error);
  });
<div id="console" />

我广泛讨论了这一解决办法:

简短的回答是you必须执行这样的呼吁:

function callback(response) {
    // Here you can do what ever you want with the response object.
    console.log(response);
}

$.ajax({
    url: "...",
    success: callback
});

Java本是单一版。

浏览器可分为三部分:

  1. 活动Loop

  2. 网播

  3. 盖特

活动休息时间持续不停,即无限期休息。 活动问题是,你的所有职能都集中在一些活动上(例如:点击)。

这是在第一个职能执行后,由一组人执行并准备完成下一个职能的活动。 也就是说,履行一项职能时,不能先开始,直到在诉讼地履行它所承担的职能。

现在,我们认为,我们把两个职能推向了一步。 一种是从服务器获取数据,另一种利用数据。 我们首先把服务器Request(Request)()功能推到电梯中,然后推到利用台的功能。 服务器检索功能在机坪上运行,并打电话给服务器,因为我们从未知道从服务器获取数据需要多少时间,因此预计这一过程需要时间,因此我们忙于忙于我们的活动循环,从而把我们一页空起来。

That s where 网播 come into the role. It takes this function from the event loop and deals with the server making the event loop free, so that we can execute the next function from the queue.

排队的下一个功能是利用垃圾处理,但由于缺乏数据,废物处理和履行下一个功能的工作一直持续到问题结束。 (这被称为“阿辛奇”,即,我们可在我们获得数据之前做其他事情。)

Let us suppose our serverRequest() function had a return statement in code. When we get back data from the server 网播, it will push it in the queue at the end of queue.

As it gets pushed at the end of the queue, we cannot utilise its data as there isn t any function left in our queue to utilise this data. Thus it is not possible to return something from the async call.

Thus the solution to this is callback or promise.

我们把我们的职能(利用从服务器返回的数据)交给一个称作服务器的职能。

function doAjax(callbackFunc, method, url) {
    var xmlHttpReq = new XMLHttpRequest();
    xmlHttpReq.open(method, url);
    xmlHttpReq.onreadystatechange = function() {

        if (xmlHttpReq.readyState == 4 && xmlHttpReq.status == 200) {
            callbackFunc(xmlHttpReq.responseText);
        }
    }
    xmlHttpReq.send(null);
}

载于我的代码。 它称为:

function loadMyJson(categoryValue){
    if(categoryValue === "veg")
        doAjax(print, "GET", "http://localhost:3004/vegetables");
    else if(categoryValue === "fruits")
        doAjax(print, "GET", "http://localhost:3004/fruits");
    else
      console.log("Data not found");
}

Javagust.info callsback

2017 answer: you can now do exactly what you want in every current browser and Node.js

这非常简单:

  • Return a Promise
  • Use the await , which will tell JavaScript to await the promise to be resolved into a value (like the HTTP response)
  • Add the async keyword to the parent function

本文是您的法典工作版本:

(async function(){

    var response = await superagent.get( ... )
    console.log(response)

})()

http://caniuse.com/#search=await”rel=“noreferer”> 等待的是所有现有浏览器和Node.js 8

你们可以利用这个习俗图书馆(用假日文撰写)来发出远程电话。

function $http(apiConfig) {
    return new Promise(function (resolve, reject) {
        var client = new XMLHttpRequest();
        client.open(apiConfig.method, apiConfig.url);
        client.send();
        client.onload = function () {
            if (this.status >= 200 && this.status < 300) {
                // Performs the function "resolve" when this.status is equal to 2xx.
                // Your logic here.
                resolve(this.response);
            }
            else {
                // Performs the function "reject" when this.status is different than 2xx.
                reject(this.statusText);
            }
        };
        client.onerror = function () {
            reject(this.statusText);
        };
    });
}

简单使用实例:

$http({
    method:  get ,
    url:  google.com 
}).then(function(response) {
    console.log(response);
}, function(error) {
    console.log(error)
});

1. A first stumbling step

As for many others, my encounter with asynchronous calls was puzzling at first.
I don t remember the details, but I may have tried something like:

let result;

$.ajax({
  url:  https://jsonplaceholder.typicode.com/todos/1 ,
  success: function (response) {
    console.log( 
Inside $.ajax: );
    console.log(response);
    result = response;
  },
});

console.log( Finally, the result:   + result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

Whoops!
The output of the line console.log( Finally, the result: + result); which I thought would be printed last, is printed before the other output!
– And it doesn t contain the result: it just prints undefined. 1
How come?

A helpful insight

I distinctly remember my first aha (?) moment about asynchronous calls. It was :

you actually don t want to get the data out of a callback; you want to get your data-needing action into the callback! 2

上文的例子就是这样。

2. Plain JavaScript and a callback function

传真: 在答复完成后,处理答复的不同步呼吁。

One alternative is the use of a callback function in a continuation-passing style : 3

const url =  https://jsonplaceholder.typicode.com/todos/2 ;

function asynchronousFunc(callback) {
  const request = new XMLHttpRequest();
  request.open( GET , url);
  request.send();
  request.onload = function () {
    if (request.readyState === request.DONE) {
      console.log( The request is done. Now calling back. );
      callback(request.responseText);
    }
  };
}

asynchronousFunc(function (result) {
  console.log( This is the start of the callback function. Result: );
  console.log(result);
  console.log( The callback function finishes on this line. THE END! );
});

console.log( LAST in the code, but executed FIRST! );
.as-console-wrapper { max-height: 100% !important; top: 0; }

Note how the function asynchronousFunc is void. It returns nothing.
asynchronousFunc is called with an anonymous callback function,
(asynchronousFunc(function (result) {...});).
This executes the desired actions on the result after the request has completed – when the responseText is available.

Running the above snippet shows how I will probably not want to write any code after the asynchronous call (such as the line LAST in the code, but executed FIRST!).
Why? – Because such code will run before the asynchronous call delivers any response data.
Doing so is bound to cause confusion when comparing the code with the output.

3. Promise with .then()

The .then() construct was introduced in the ECMA-262 6th Edition in June 2015.
The code below is plain JavaScript, replacing the old-school XMLHttpRequest with Fetch. 4

fetch( https://api.chucknorris.io/jokes/random )
  .then((response) => response.json())
  .then((responseBody) => {
    console.log( Using .then() : );
    console.log(responseBody.value +  
 );
  });
.as-console-wrapper { max-height: 100% !important; top: 0; }

4. Promise with async/await

<代码>sync/> 建造工作于2017年6月第8版ECMA-262>。

async function awaitAndReceivePromise() {
  const responseBody = (
    await fetch( https://api.quotable.io/quotes/random )
  ).json();
  console.log( Using async/await: );
  const obj = (await responseBody)[0];
  console.log( "  + obj.content +  " –   + obj.author +  
 );
}

awaitAndReceivePromise();
.as-console-wrapper { max-height: 100% !important; top: 0; }

A word of warning is warranted if you decide to go with the async/await construct. Note in the above snippet how await is needed in two places.
If forgotten in the first place, there will be no output at all. If forgotten in the second place, the only output will be Using async/await: – nothing else gets printed.
Forgetting the async prefix of the function is maybe the worst of all – you ll get a "SyntaxError" – and likely no hint about the missing async keyword.


上述所有例子都简明扼要地传达了如何用不同步的电话来诋毁APIC。 <>5>

References


1 Expressed by the asker of the question as they all return undefined.

2 Here is more on how asynchronous calls may be confusing at first.

3 Like the X in AJAX, the name XMLHttpRequest is misleading – it can be used to retrieve any type of data, not just XML.
These days, the data format of Web APIs is ubiquitously JSON, not XML.

4 Fetch returns a Promise. I was surprised to learn that neither XMLHttpRequest nor Fetch are part of the ECMAScript standard. The reason JavaScript can access them here is that the web browser provides them.
The Fetch Standard and the XMLHttpRequest Standard are both upheld by the Web Hypertext Application Technology Working Group which was formed in June 2004.

5 You might also be interested in How can I fetch an array of URLs with Promise.all?.

ECMA 成文6有发电机,使你能够轻松地进行节目。

function* myGenerator() {
    const callback = yield;
    let [response] = yield $.ajax("https://stackoverflow.com", {complete: callback});
    console.log("response is:", response);

    // examples of other things you can do
    yield setTimeout(callback, 1000);
    console.log("it delayed for 1000ms");
    while (response.statusText === "error") {
        [response] = yield* anotherGenerator();
    }
}

采用上述准则:

const gen = myGenerator(); // Create generator
gen.next(); // Start it
gen.next((...args) => gen.next([...args])); // Set its callback function

如果你需要瞄准不支持ES6的浏览器,那么你可以通过Babel或关闭公司操作该代码,以产生ECMA第5版。

背书的<代码>......args在阅读时按阵列加以包装和结构化,以便该模式能够应对有多种论点的反馈。 For example with node fs:

const [err, data] = yield fs.readFile(filePath, "utf-8", callback);

我们发现,我们是一个似乎在我们称之为“时代”的层面取得进展的宇宙。 我们确实不理解什么时候了,但我们已经形成了一些抽象和词汇,让我们有理由和谈论:“......”、“......”、“......”、“......”、“......前””。

The computer systems we build--more and more--have time as an important dimension. Certain things are set up to happen in the future. Then other things need to happen after those first things eventually occur. This is the basic notion called "asynchronicity". In our increasingly networked world, the most common case of asynchronicity is waiting for some remote system to respond to some request.

例如。 你叫牛奶,订购一些牛奶。 到了此为止,你想把它放在你的咖啡里。 你现在可以把牛奶放在咖啡里,因为牛奶还没有到这里。 你们必须等到来,才把它放在咖啡里。 换言之,以下工作赢得了:

var milk = order_milk();
put_in_coffee(milk);

Because JavaScript has no way to know that it needs to wait for order_milk to finish before it executes put_in_coffee. In other words, it does not know that order_milk is asynchronous--is something that is not going to result in milk until some future time. JavaScript, and other declarative languages execute one statement after another without waiting.

传统的 Java本式办法解决这一问题,利用 Java文支持可以环绕的头等物体的功能,就是把功能作为准时请求的参数,然后在 future完成未来某个时候的任务时将援引这一要求。 这就是“回顾”办法。 它希望:

order_milk(put_in_coffee);

然后,当牛奶到达时,它才会援引<条码>输出_in_coffee。

这一反馈办法的问题是,它污染了以<代码>return<>/code>报告其结果的职能的正常属性;相反,职能不能通过称为“参数”来报告其结果。 而且,在处理更长的事件顺序时,这种做法可能迅速变得不舒服。 例如,我要说,我要等到把牛奶放在咖啡里,然后才采取第三步,即喝咖啡。 我最后需要写这样的东西:

order_milk(function(milk) { put_in_coffee(milk, drink_coffee); }

where I am passing to put_in_coffee both the milk to put in it, and also the action (drink_coffee) to execute once the milk has been put in. Such code becomes hard to write, and read, and debug.

在此情况下,我们可以把该守则改成:

var answer;
$.ajax( /foo.json ) . done(function(response) {
  callback(response.data);
});

function callback(data) {
  console.log(data);
}

Enter promises

This was the motivation for the notion of a "promise", which is a particular type of value which represents a future or asynchronous outcome of some sort. It can represent something that already happened, or that is going to happen in the future, or might never happen at all. Promises have a single method, named then, to which you pass an action to be executed when the outcome the promise represents has been realized.

就我们的牛奶和咖啡而言,我们设计了order_milk,以换取对牛奶的进口,然后具体指明put_in_coffee,作为then的行动:

order_milk() . then(put_in_coffee)

其中一个优势是,我们可以共同加以扼杀,以制定今后发生事件的顺序(“链条”):

order_milk() . then(put_in_coffee) . then(drink_coffee)

请允许我对你的特殊问题做出承诺。 我们将在一项职能中总结我们的要求逻辑,这一职能兑现了以下承诺:

function get_data() {
  return $.ajax( /foo.json );
}

实际上,我们所做的一切都添加到<代码>return上。 这是因为j Query s $.ajax。 类似允诺的东西已经恢复。 (在实践中,在不了解细节的情况下,我们宁愿总结这一呼吁,以换取真正的许诺,或采用替代$.ajax的某种办法。 现在,如果我们想装上档案,等待完成,然后做一些事情,我们只能说什么。

get_data() . then(do_something)

例如,

get_data() .
  then(function(data) { console.log(data); });

在使用允诺时,我们最终将许多职能推向then<>/code>,因此,使用更紧凑的ES6型arrow功能往往是有益的:

get_data() .
  then(data => console.log(data));

The async keyword

But there s still something vaguely dissatisfying about having to write code one way if synchronous and a quite different way if asynchronous. For synchronous, we write

a();
b();

but if a is asynchronous, with promises we have to write

a() . then(b);

首先,我们说,“贾瓦文没有办法知道它需要wait,以便第一次呼吁完成,然后执行第二次”。 如果有?,有某种方式告诉贾瓦文的话,这是否是 n? 由此可见,在称为“async”功能的特殊职能类别中使用了“await的关键词。 这一特征是即将出版的欧洲复兴开发银行(ES)版本的一部分,但是,根据正确的序号,已经在转播器中提供,例如Babel。 这使我们能够简单地写字

async function morning_routine() {
  var milk   = await order_milk();
  var coffee = await put_in_coffee(milk);
  await drink(coffee);
}

如果是的话,你会写好像什么东西。

async function foo() {
  data = await get_data();
  console.log(data);
}

Here are some approaches to work with asynchronous requests:

  1. Browser Promise object
  2. Q - A promise library for JavaScript
  3. A+ Promises.js
  4. jQuery deferred
  5. XMLHttpRequest API
  6. Using callback concept - As implementation in first answer

Example: jQuery deferred implementation to work with multiple requests

var App = App || {};

App = {
    getDataFromServer: function(){

      var self = this,
                 deferred = $.Deferred(),
                 requests = [];

      requests.push($.getJSON( request/ajax/url/1 ));
      requests.push($.getJSON( request/ajax/url/2 ));

      $.when.apply(jQuery, requests).done(function(xhrResponse) {
        return deferred.resolve(xhrResponse.result);
      });
      return deferred;
    },

    init: function(){

        this.getDataFromServer().done(_.bind(function(resp1, resp2) {

           // Do the operations which you wanted to do when you
           // get a response from Ajax, for example, log response.
        }, this));
    }
};
App.init();

www.un.org/Depts/DGACM/index_spanish.htm 简短回答:foo() 即刻返回,而$ajax( 电话在职能回报后执行。 那么,问题是如何或是在什么地方储存“yn”一回来就收回的结果。

Several solutions have been given in this thread. Perhaps the easiest way is to pass an object to the foo() method, and to store the results in a member of that object after the async call completes.

function foo(result) {
    $.ajax({
        url:  ... ,
        success: function(response) {
            result.response = response;   // Store the async result
        }
    });
}

var result = { response: null };   // Object to hold the async result
foo(result);                       // Returns before the async completes

请注意,<代码>foo(>>”的号召仍无用。 然而,“合成”呼吁的结果现在将储存在<代码>result.response上。

Use a callback() function inside the foo() success. Try it in this way. It is simple and easy to understand.

var lat = "";
var lon = "";

function callback(data) {
    lat = data.lat;
    lon = data.lon;
}

function getLoc() {
    var url = "http://ip-api.com/json"
    $.getJSON(url, function(data) {
        callback(data);
    });
}

getLoc();

Using Promise

对这一问题的最完善的答复是使用<条码>Promise

function ajax(method, url, params) {
  return new Promise(function(resolve, reject) {
    var xhr = new XMLHttpRequest();
    xhr.onload = function() {
      resolve(this.responseText);
    };
    xhr.onerror = reject;
    xhr.open(method, url);
    xhr.send(params);
  });
}

Usage

ajax("GET", "/test", "acrive=1").then(function(result) {
    // Code depending on result
})
.catch(function() {
    // An error occurred
});

But wait...!

使用承诺是一个问题!

Why should we use our own custom Promise?

在我发现旧浏览器有错误之前,我使用这一解决办法:

不详 rror: Promise没有定义

因此,我决定执行我自己的“灵敏”班,ES3至。 如果没有定义, Java本编辑。 在你的主要法典之前添加这一法典,然后安全使用假想!

if(typeof Promise === "undefined"){
    function _typeof(obj) { "@babel/helpers - typeof"; return 

    _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
    function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
    function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.
In order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
    function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
    function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
    function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
    function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
    function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
    function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
    function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
    function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
    function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
    var Promise = /*#__PURE__*/function () {
  "use strict";

  function Promise(main) {
    _classCallCheck(this, Promise);
    this.main = main;
    this.mainExecuted = false;
    this.resolved = false;
    this.rejected = false;
    this.promiseChain = [];
    this.handleError = function () {};
    this.onResolve = this.onResolve.bind(this);
    this.onReject = this.onReject.bind(this);
  }
  _createClass(Promise, [{
    key: "then",
    value: function then(handleSuccess) {
      if (this.resolved) {
        if (!this.rejected) {
          this.args = handleSuccess(this.args);
        }
      } else {
        this.promiseChain.push(handleSuccess);
        this.main(this.onResolve, this.onReject);
        this.thenExecuted = true;
      }
      return this;
    }
  }, {
    key: "catch",
    value: function _catch(handleError) {
      this.handleError = handleError;
      if (!this.mainExecuted) {
        this.main(this.onResolve, this.onReject);
        this.thenExecuted = true;
      }
      return this;
    }
  }, {
    key: "onResolve",
    value: function onResolve() {
      var _this = this;
      this.resolved = true;
      for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
        args[_key] = arguments[_key];
      }
      this.args = args;
      try {
        this.promiseChain.forEach(function (nextFunction) {
          _this.args = nextFunction.apply(void 0, _toConsumableArray(_this.args));
        });
      } catch (error) {
        this.promiseChain = [];
        this.onReject(error);
      }
    }
  }, {
    key: "onReject",
    value: function onReject(error) {
      this.rejected = true;
      this.handleError(error);
    }
  }]);
  return Promise;
}();
}

利用ES2017号,你应将此称为功能声明。

async function foo() {
  var response = await $.ajax({url:  ... })
  return response;
}

并如此执行。

(async function() {
  try {
    var result = await foo()
    console.log(result)
  } catch (e) {}
})()

或Promise syntax。

foo().then(response => {
  console.log(response)

}).catch(error => {
  console.log(error)

})

Stack Snippet表明上述准则。

// The function declaration:
async function foo() {
  var response = await $.ajax({
    url:  https://jsonplaceholder.typicode.com/todos/1 
  })
  return response;
}

// Execute it like this:
(async function() {
  try {
    var result = await foo()
    console.log(result)
  } catch (e) {}
})()

// Or use Promise syntax:
foo().then(response => {
  console.log(response)
}).catch(error => {
  console.log(error)
})
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src=
"https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

当然,有许多办法,如同步要求、许诺,但根据我的经验,我认为你应当采用反馈办法。 它是Script的自然行为。

因此,你的法典可以改写,没有什么不同:

function foo() {
    var result;

    $.ajax({
        url:  ... ,
        success: function(response) {
            myCallback(response);
        }
    });

    return result;
}

function myCallback(response) {
    // Does something.
}

问题是:

我怎么回过声回击?

http://www.un.org

How to make asynchronous 代码:synchronous?

解决办法是避免退约,同时使用<>Promises和sync/await

我要举一个例子说明阿贾克斯的请求。

(Although it can be written in JavaScript, I prefer to write it in Python, and compile it to JavaScript using Transcrypt. It will be clear enough.)

让我们首先能够使用j Query,将$作为。 S:

__pragma__ ( alias ,  S ,  $ )

界定一项职能,即:

def read(url: str):
    deferred = S.Deferred()
    S.ajax({ type : "POST",  url : url,  data : { },
         success : lambda d: deferred.resolve(d),
         error : lambda e: deferred.reject(e)
    })
    return deferred.promise()

Use the asynchronous code as if it were synchronous:

async def readALot():
    try:
        result1 = await read("url_1")
        result2 = await read("url_2")
    except Exception:
        console.warn("Reading a lot failed")




相关问题
selected text in iframe

How to get a selected text inside a iframe. I my page i m having a iframe which is editable true. So how can i get the selected text in that iframe.

How to fire event handlers on the link using javascript

I would like to click a link in my page using javascript. I would like to Fire event handlers on the link without navigating. How can this be done? This has to work both in firefox and Internet ...

How to Add script codes before the </body> tag ASP.NET

Heres the problem, In Masterpage, the google analytics code were pasted before the end of body tag. In ASPX page, I need to generate a script (google addItem tracker) using codebehind ClientScript ...

Clipboard access using Javascript - sans Flash?

Is there a reliable way to access the client machine s clipboard using Javascript? I continue to run into permissions issues when attempting to do this. How does Google Docs do this? Do they use ...

javascript debugging question

I have a large javascript which I didn t write but I need to use it and I m slowely going trough it trying to figure out what does it do and how, I m using alert to print out what it does but now I ...

Parsing date like twitter

I ve made a little forum and I want parse the date on newest posts like twitter, you know "posted 40 minutes ago ","posted 1 hour ago"... What s the best way ? Thanx.