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

如何從異步調(diào)用返回響應(yīng)?
P粉668113768
P粉668113768 2023-08-23 12:49:32
0
2
727
<p>如何從發(fā)出異步請(qǐng)求的函數(shù) <code>foo</code> 返回響應(yīng)/結(jié)果?</p> <p>我試圖從回調(diào)中返回值,并將結(jié)果分配給函數(shù)內(nèi)的局部變量并返回該變量,但這些方法都沒有實(shí)際返回響應(yīng) - 它們都返回 <code>undefined< /code> 或變量 <code>result</code> 的初始值。</code></p><code> <p><strong>接受回調(diào)的異步函數(shù)示例</strong>(使用 jQuery 的 <code>ajax</code> 函數(shù)):</p> <pre class="brush:php;toolbar:false;">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` }</pre> <p><strong>使用 Node.js 的示例:</strong></p> <pre class="brush:php;toolbar:false;">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` }</pre> <p><strong>使用 Promise 的 <code>then</code> 塊的示例:</strong></p> <pre class="brush:php;toolbar:false;">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` }</pre> <p><br /></p></code>
P粉668113768
P粉668113768

全部回復(fù)(2)
P粉334721359

如果您沒有在代碼中使用 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 的人編寫答案,但我決定為不使用 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í),您定義的偵聽器尚未執(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)編寫代碼,告訴您的程序在計(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 上開始指南。

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)行包含“正常”代碼的函數(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ī)給你回電。你掛斷電話,離開家,做你計(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)格”編寫異步。代碼仍然是異步的,但更容易閱讀/理解。

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

重要提示:您只能在 async 函數(shù)或 await .org/en-US/docs/Web/JavaScript/Guide/Modules" rel="noreferrer">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)編寫代碼比看起來(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)鳥)。

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

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

這是使用 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; }
最新下載
更多>
網(wǎng)站特效
網(wǎng)站源碼
網(wǎng)站素材
前端模板