簡體   English   中英

淘汰賽JS-承諾遞歸

[英]Knockout JS - Promise recursion

在這種情況下,我必須更新綁定到HTML元素的可觀察的可觀察對象,並且其值正在通過異步操作(從服務器中獲取)進行更新。

我編寫了以下示例代碼:

 const viewModel = function() { const self = this; self.fetchResults = function() { const id = ko.observable(0); fetch("https://jsonplaceholder.typicode.com/photos") .then(function(response) { return response.json(); }) .then(function(data) { id(data.length); console.log(id()); }) return id; }; }; ko.applyBindings(new viewModel()); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script> <div data-bind="text: fetchResults()"></div> 

它正在創建一個無限的遞歸循環。

敲除是否在異步函數中更新值而重復調用該函數? 可能是此問題的根本原因是什么?

TIA!

編輯:

我在頁面上有多個HTML元素,要求將不同的信息綁定到它們,例如,

<div data-bind="text: fetchResults('some-url')"></div>
<div data-bind="text: fetchResults('some-different-url')"></div>
<div data-bind="text: fetchResults('another-url-altogether')"></div>

那意味着我需要在我執行的fetchResults函數內部創建可觀察的(如果我的理解fetchResults ,請更正我:)

問題在於,由於您正在使用表達式,因此該函數將在render上運行,並返回一個可觀察的對象。 當可觀察對象的值更改時,它將使視圖的該部分再次呈現,從而再次調用該函數,並永遠循環。

在評論中,您說過:

實際上,我需要針對同一頁面中的不同提取URI多次調用此方法,並將其綁定到單獨的HTML元素。

...並將此示例添加到問題中:

 <div data-bind="text: fetchResults('some-url')"></div> <div data-bind="text: fetchResults('some-different-url')"></div> <div data-bind="text: fetchResults('another-url-altogether')"></div> 

那確實改變了一點。 我可能會使用自定義綁定而不是函數:

 ko.bindingHandlers.textFetch = { update(element, valueAccessor) { const url = ko.unwrap(valueAccessor()); element.textContent = "0"; fetch(url) .then((response) => { if (!response.ok) { throw new Error("HTTP error " + response.status); } return response.json(); }) .then((data) => { element.textContent = data.length; }); } }; const viewModel = function() { }; ko.applyBindings(new viewModel()); 
 <div data-bind="textFetch: 'https://jsonplaceholder.typicode.com/photos'"></div> <div data-bind="textFetch: 'https://jsonplaceholder.typicode.com/posts'"></div> <div data-bind="textFetch: 'https://jsonplaceholder.typicode.com/comments'"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script> 


但是,如果要使其與當前代碼更相似,請保留可觀察的URL緩存:

 const viewModel = function() { const self = this; // In a modern environment, `observables` could be a Map rather than an object const observables = Object.create(null); self.fetchResults = function(url) { // Get the observable if we have it let id = observables[url]; if (!id) { // We don't, create and remember one, do the fetch id = observables[url] = ko.observable(0); fetch(url) .then(function(response) { return response.json(); }) .then(function(data) { id(data.length); }) } return id; }; }; ko.applyBindings(new viewModel()); 
 <div data-bind="text: fetchResults('https://jsonplaceholder.typicode.com/photos')"></div> <div data-bind="text: fetchResults('https://jsonplaceholder.typicode.com/posts')"></div> <div data-bind="text: fetchResults('https://jsonplaceholder.typicode.com/comments')"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script> 


旁注:您不會在fetch回調中檢查是否成功。 您不是唯一的一個,我會說fetch API的設計很差,因為我看到這支步槍幾乎每天都在SO上被觸發。 我已經在貧乏的小博客上寫下了它 ,但是基本上,您需要添加:

if (!response.ok) {
  throw new Error("HTTP error " + response.status);
}

...在您的履行處理程序中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM