国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

Wie kann ich eine Antwort von einem asynchronen Aufruf zurückgeben?
P粉668113768
P粉668113768 2023-08-23 12:49:32
0
2
725
<p>Wie gebe ich eine Antwort/ein Ergebnis von einer Funktion <code>foo</code> zurück, die eine asynchrone Anfrage stellt? </p> <p>Ich habe versucht, den Wert aus dem Rückruf zurückzugeben und das Ergebnis einer lokalen Variablen innerhalb der Funktion zuzuweisen und diese Variable zurückzugeben, aber keine dieser Methoden gibt tats?chlich eine Antwort zurück – sie alle geben <code>undefiniert< oder eine Variable Der Anfangswert von <code>result</code>. </code></p><code> <p><strong>Beispiel einer asynchronen Funktion, die einen Rückruf akzeptiert</strong> (unter Verwendung der Funktion <code>ajax</code> von jQuery): </p> <pre class="brush:php;toolbar:false;">function foo() { var-Ergebnis; $.ajax({ URL: '...', Erfolg: Funktion(Antwort) { Ergebnis = Antwort; // Antwort zurückgeben; // <- Das habe ich auch versucht } }); return result; // Es gibt immer ?undefiniert“ zurück }</pre> <p><strong>Beispiel mit Node.js:</strong></p> <pre class="brush:php;toolbar:false;">function foo() { var-Ergebnis; fs.readFile("path/to/file", function(err, data) { Ergebnis = Daten; // return data; // <- Das habe ich auch versucht }); return result; // Es gibt immer ?undefiniert“ zurück }</pre> <p><strong>Beispiel für einen <code>then</code>-Block mit Promise: </strong></p> <pre class="brush:php;toolbar:false;">function foo() { var-Ergebnis; fetch(url).then(function(response) { Ergebnis = Antwort; // Antwort zurückgeben; // <- Das habe ich auch versucht }); return result; // Es gibt immer ?undefiniert“ zurück }</pre> <p><br /></p></code>
P粉668113768
P粉668113768

Antworte allen(2)
P粉334721359

如果您沒(méi)有在代碼中使用 jQuery,這個(gè)答案適合您

你的代碼應(yīng)該是這樣的:

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

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

菲利克斯·克林做得很好工作為使用 jQuery for AJAX 的人編寫(xiě)答案,但我決定為不使用 jQuery 的人提供替代方案。

(注意,對(duì)于那些使用新的 fetch API、Angular 或 Promise 的人,我添加了另一個(gè)答案如下


你面臨的問(wèn)題

這是另一個(gè)答案中“問(wèn)題的解釋”的簡(jiǎn)短摘要,如果您在閱讀后不確定,請(qǐng)閱讀該答案。

AJAX 中的 A 代表異步。這意味著發(fā)送請(qǐng)求(或者更確切地說(shuō)接收響應(yīng))被從正常執(zhí)行流程中刪除。在您的示例中, .send code> 立即返回,并且在調(diào)用您作為 success 回調(diào)傳遞的函數(shù)之前執(zhí)行下一條語(yǔ)句 return result;。

這意味著當(dāng)您返回時(shí),您定義的偵聽(tīng)器尚未執(zhí)行,這意味著您返回的值尚未定義。

這是一個(gè)簡(jiǎn)單的類比:

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

(小提琴)

由于 a=5 部分尚未執(zhí)行,因此返回的 a 值為 undefined。 AJAX 的行為是這樣的,您在服務(wù)器有機(jī)會(huì)告訴您的瀏覽器該值是什么之前就返回了該值。

此問(wèn)題的一個(gè)可能的解決方案是重新主動(dòng)編寫(xiě)代碼,告訴您的程序在計(jì)算完成后要做什么。

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

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

這稱為CPS?;旧?,我們向 getFive 傳遞一個(gè)要在完成時(shí)執(zhí)行的操作,我們告訴我們的代碼如何在事件完成時(shí)做出反應(yīng)(例如我們的 AJAX 調(diào)用,或者在本例中是超時(shí))。

用法是:

getFive(onComplete);

屏幕上會(huì)提示“5”。 (小提琴)。

可能的解決方案

解決這個(gè)問(wèn)題基本上有兩種方法:

  1. 使 AJAX 調(diào)用同步(我們稱之為 SJAX)。
  2. 重構(gòu)您的代碼,以便與回調(diào)一起正常工作。

1。同步 AJAX - 不要這樣做!!

至于同步 AJAX,不要這樣做!Felix 的回答提出了一些令人信服的論點(diǎn),說(shuō)明為什么這是一個(gè)壞主意。總而言之,它會(huì)凍結(jié)用戶的瀏覽器,直到服務(wù)器返回響應(yīng)并造成非常糟糕的用戶體驗(yàn)。以下是來(lái)自 MDN 的另一個(gè)簡(jiǎn)短總結(jié),說(shuō)明原因:

如果您不得不這樣做,您可以傳遞一個(gè)標(biāo)志。 具體方法如下

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。重組代碼

讓您的函數(shù)接受回調(diào)。在示例代碼中,可以使 foo 接受回調(diào)。我們將告訴代碼當(dāng) foo 完成時(shí)如何反應(yīng)。

所以:

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

變成:

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

這里我們傳遞了一個(gè)匿名函數(shù),但我們也可以輕松傳遞對(duì)現(xiàn)有函數(shù)的引用,使其看起來(lái)像:

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

有關(guān)如何完成此類回調(diào)設(shè)計(jì)的更多詳細(xì)信息,請(qǐng)查看 Felix 的回答。

現(xiàn)在,讓我們定義 foo 本身以進(jìn)行相應(yīng)的操作

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();
}

(小提琴)

現(xiàn)在,我們已經(jīng)讓 foo 函數(shù)接受一個(gè)操作,以便在 AJAX 成功完成時(shí)運(yùn)行。我們可以通過(guò)檢查響應(yīng)狀態(tài)是否不是 200 并采取相應(yīng)措施(創(chuàng)建失敗處理程序等)來(lái)進(jìn)一步擴(kuò)展此功能。它有效地解決了我們的問(wèn)題。

如果您仍然很難理解這一點(diǎn),閱讀 AJAX 獲取在 MDN 上開(kāi)始指南。

P粉642920522

問(wèn)題

Ajax 中的 A 代表 異步。這意味著發(fā)送請(qǐng)求(或者更確切地說(shuō)接收響應(yīng))被從正常執(zhí)行流程中刪除。在您的示例中,$.ajax 立即返回,并且下一條語(yǔ)句 return result; 在您作為 success 回調(diào)傳遞的函數(shù)之前執(zhí)行甚至打電話。

這是一個(gè)類比,希望可以使同步流和異步流之間的區(qū)別更加清晰:

同步

想象一下,您給朋友打電話并請(qǐng)他為您查找一些信息。盡管可能需要一段時(shí)間,但您還是在電話旁等待,凝視著太空,直到您的朋友給您所需的答案。

當(dāng)您進(jìn)行包含“正?!贝a的函數(shù)調(diào)用時(shí),也會(huì)發(fā)生同樣的情況:

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

var item = findItem();

// Do something with item
doSomethingElse();

盡管 findItem 可能需要很長(zhǎng)時(shí)間才能執(zhí)行,但 var item = findItem(); 之后的任何代碼都必須等待直到該函數(shù)返回結(jié)果。

異步

您出于同樣的原因再次給您的朋友打電話。但這次你告訴他你很著急,他應(yīng)該用你的手機(jī)給你回電。你掛斷電話,離開(kāi)家,做你計(jì)劃做的事情。一旦您的朋友給您回電,您就正在處理他提供給您的信息。

這正是您發(fā)出 Ajax 請(qǐng)求時(shí)所發(fā)生的情況。

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

不等待響應(yīng),而是立即繼續(xù)執(zhí)行,并執(zhí)行 Ajax 調(diào)用之后的語(yǔ)句。為了最終獲得響應(yīng),您需要提供一個(gè)在收到響應(yīng)后調(diào)用的函數(shù),即回調(diào)(注意到什么了嗎?回調(diào)?)。該調(diào)用之后的任何語(yǔ)句都會(huì)在調(diào)用回調(diào)之前執(zhí)行。


解決方案

擁抱 JavaScript 的異步特性!雖然某些異步操作提供同步對(duì)應(yīng)項(xiàng)(“Ajax”也是如此),但通常不鼓勵(lì)使用它們,尤其是在瀏覽器上下文中。

你問(wèn)為什么不好?

JavaScript 在瀏覽器的 UI 線程中運(yùn)行,任何長(zhǎng)時(shí)間運(yùn)行的進(jìn)程都會(huì)鎖定 UI,使其無(wú)響應(yīng)。另外,JavaScript的執(zhí)行時(shí)間是有上限的,瀏覽器會(huì)詢問(wèn)用戶是否繼續(xù)執(zhí)行。

所有這些都會(huì)導(dǎo)致非常糟糕的用戶體驗(yàn)。用戶將無(wú)法判斷一切是否正常。此外,對(duì)于網(wǎng)速較慢的用戶,效果會(huì)更差。

下面我們將介紹三種不同的解決方案,它們都是相互構(gòu)建的:

  • 帶有 async/await 的 Promise(ES2017+,如果您使用轉(zhuǎn)譯器或再生器,則可在舊版瀏覽器中使用)
  • 回調(diào)(在節(jié)點(diǎn)中流行)
  • 帶有 then() 的 Promise(ES2015+,如果您使用眾多 Promise 庫(kù)之一,則可在舊版瀏覽器中使用)

這三個(gè)功能均可在當(dāng)前瀏覽器和 Node 7+ 中使用。


ES2017+:使用 async/await 進(jìn)行承諾

2017 年發(fā)布的 ECMAScript 版本引入了對(duì)異步函數(shù)的語(yǔ)法級(jí)支持。借助asyncawait,您可以以“同步風(fēng)格”編寫(xiě)異步。代碼仍然是異步的,但更容易閱讀/理解。

async/await 構(gòu)建在 Promise 之上:async 函數(shù)始終返回 Promise。 await “解開(kāi)”一個(gè) Promise,并且要么產(chǎn)生 Promise 被解析的值,要么在 Promise 被拒絕時(shí)拋出錯(cuò)誤。

重要提示:您只能在 async 函數(shù)或 JavaScript 模塊。模塊外部不支持頂級(jí) await,因此您可能必須創(chuàng)建異步 IIFE (立即調(diào)用函數(shù)表達(dá)式)來(lái)啟動(dòng)異步上下文(如果不使用模塊)。

您可以閱讀有關(guān)asyncawait

這是一個(gè)詳細(xì)說(shuō)明上面的延遲函數(shù)findItem()的示例:

// 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);
})();

當(dāng)前瀏覽器node 版本支持 async/await。您還可以借助 regenerator (或使用 regenerator 的工具)將代碼轉(zhuǎn)換為 ES5,以支持較舊的環(huán)境,例如 Babel)。


讓函數(shù)接受回調(diào)

回調(diào)是指函數(shù) 1 傳遞給函數(shù) 2 時(shí)。函數(shù) 2 可以在函數(shù) 1 準(zhǔn)備好時(shí)調(diào)用它。在異步進(jìn)程的上下文中,只要異步進(jìn)程完成,就會(huì)調(diào)用回調(diào)。通常,結(jié)果會(huì)傳遞給回調(diào)。

在問(wèn)題的示例中,您可以使 foo 接受回調(diào)并將其用作 success 回調(diào)。所以這個(gè)

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

變成了

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

這里我們定義了“內(nèi)聯(lián)”函數(shù),但您可以傳遞任何函數(shù)引用:

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

foo(myCallback);

foo 本身定義如下:

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

callback 將引用我們調(diào)用時(shí)傳遞給 foo 的函數(shù),并將其傳遞給 success。 IE。一旦Ajax請(qǐng)求成功,$.ajax將調(diào)用callback并將響應(yīng)傳遞給回調(diào)(可以用result引用,因?yàn)檫@就是我們定義回調(diào)的方式)。

您還可以在將響應(yīng)傳遞給回調(diào)之前對(duì)其進(jìn)行處理:

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

使用回調(diào)編寫(xiě)代碼比看起來(lái)更容易。畢竟,瀏覽器中的 JavaScript 很大程度上是事件驅(qū)動(dòng)的(DOM 事件)。接收 Ajax 響應(yīng)只不過(guò)是一個(gè)事件。 當(dāng)您必須使用第三方代碼時(shí)可能會(huì)出現(xiàn)困難,但大多數(shù)問(wèn)題只需思考應(yīng)用程序流程就可以解決。


ES2015+:帶有 then()的 Promise >

Promise API 是一個(gè)新的ECMAScript 6 (ES2015) 的功能,但它已經(jīng)具有良好的瀏覽器支持。還有許多庫(kù)實(shí)現(xiàn)了標(biāo)準(zhǔn) Promises API 并提供了其他方法來(lái)簡(jiǎn)化異步函數(shù)的使用和組合(例如,藍(lán)鳥(niǎo))。

Promise 是未來(lái)值的容器。當(dāng) Promise 收到值(已解決)或被取消(拒絕)時(shí),它會(huì)通知所有想要訪問(wèn)該值的“偵聽(tīng)器”。

與普通回調(diào)相比的優(yōu)點(diǎn)是它們?cè)试S您解耦代碼并且更容易編寫(xiě)。

這是使用 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);
  });
}

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; }
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage