繁体   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