首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在$.each完成迭代之后执行某些内容?

如何在$.each完成迭代之后执行某些内容?
EN

Stack Overflow用户
提问于 2020-07-20 09:17:02
回答 3查看 58关注 0票数 1

基本上,我有一个非常简单的计数器,它从5个不同的位置加载JSON文件,并计算条目的数量:

代码语言:javascript
运行
复制
let count = {
    1: 0,
    2: 0,
    3: 0,
    4: 0,
    5: 0,
    total: 0
};

let url = {
    1: "https://jsonplaceholder.typicode.com/posts",
    2: "https://jsonplaceholder.typicode.com/comments",
    3: "https://jsonplaceholder.typicode.com/albums",
    4: "https://jsonplaceholder.typicode.com/todos",
    5: "https://jsonplaceholder.typicode.com/users"
};

function fetchJSONList(url) {
    return new Promise(function(resolve, reject) {
        fetch(url)
            .then(response => { return response.json(); })
            .then(resolve)
            .catch(reject);
    });
}

function checkAll() {
    return new Promise(function(resolve, reject) {
        $.each(url, function(key) {
            fetchJSONList(url[key])
                .then(list => {
                    if ($.isEmptyObject(list)) {
                        const spanID = "#api-" + key;
                        $(spanID).text(0);
                    }
                    $.each(list, function() {
                        count[key]++;
                        count.total++;

                        const spanID = "#api-" + key;
                        $(spanID).text(count[key]);
                    });
                })
                .catch(reject);
        });
        resolve();
    });
}

checkAll()
    .then($("#count-total").text(count.total))
    .catch(console.log);
代码语言:javascript
运行
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<ul id="site-list">
        <li><span>API 1: </span><span id="api-1">Loading...</span></li>
        <li><span>API 2: </span><span id="api-2">Loading...</span></li>
        <li><span>API 3: </span><span id="api-3">Loading...</span></li>
        <li><span>API 4: </span><span id="api-4">Loading...</span></li>
        <li><span>API 5: </span><span id="api-5">Loading...</span></li>
</ul>
    
<span>Total: </span><span id="count-total">Loading...</span>

如您所见,在脚本加载后立即将总量更新为"0“(即函数checkAll()返回的承诺立即被解析)。但是,我希望只有在$.each完成对url变量的迭代之后才更新总价值。

有什么办法吗?

编辑:,所以考虑T.J.Crowder的答案,

代码语言:javascript
运行
复制
let count = {
    1: 0,
    2: 0,
    3: 0,
    4: 0,
    5: 0,
    total: 0
};

let url = {
    1: "https://jsonplaceholder.typicode.com/posts",
    2: "https://jsonplaceholder.typicode.com/comments",
    3: "https://jsonplaceholder.typicode.com/albums",
    4: "https://jsonplaceholder.typicode.com/todos",
    5: "https://jsonplaceholder.typicode.com/users"
};

function fetchJSONList(url) {
    return new Promise(function(resolve, reject) {
        fetch(url)
            .then(response => { return response.json(); })
            .then(resolve)
            .catch(reject);
    });
}

Promise
.all(
    Object.entries(url).map(([key, value]) => {
        fetchJSONList(value)
            .then(list => {
                if ($.isEmptyObject(list)) {
                    const spanID = "#api-" + key;
                    $(spanID).text(0);
                }
                $.each(list, function() {
                    count[key]++;
                    count.total++;

                    const spanID = "#api-" + key;
                    $(spanID).text(count[key]);
                });
            })
    })
)
.then($("#count-total").text(count.total))
.catch(console.log);
代码语言:javascript
运行
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<ul id="site-list">
        <li><span>API 1: </span><span id="api-1">Loading...</span></li>
        <li><span>API 2: </span><span id="api-2">Loading...</span></li>
        <li><span>API 3: </span><span id="api-3">Loading...</span></li>
        <li><span>API 4: </span><span id="api-4">Loading...</span></li>
        <li><span>API 5: </span><span id="api-5">Loading...</span></li>
</ul>
    
<span>Total: </span><span id="count-total">Loading...</span>

欢迎还是没运气。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-07-20 09:21:14

但是,

希望只有在$.each遍历了url变量之后才更新总价值。

嗯,是的。-)只是$.each不等待它开始完成的异步进程。

如果希望所有的承诺同时运行,请使用map收集承诺,使用Promise.all等待所有承诺的实现(或其中的一个被拒绝):

代码语言:javascript
运行
复制
function checkAll() {
    return Promise.all(Object.entries(url).map(([key, value]) =>
        fetchJSONList(value)
            .then(list => {
                if ($.isEmptyObject(list)) {
                    const spanID = "#api-" + key;
                    $(spanID).text(0);
                }
                $.each(list, function() {
                    count[key]++;
                    count.total++;

                    const spanID = "#api-" + key;
                    $(spanID).text(count[key]);
                });
            })
    ));
}

您还需要在这里修复对then的调用:

代码语言:javascript
运行
复制
.then($("#count-total").text(count.total))

调用 $(/*...*/).text(/*...*/)并将返回值传递给then。您希望向then传递一个函数:

代码语言:javascript
运行
复制
.then(() => $("#count-total").text(count.total))

而且,没有理由在new Promise中使用fetchJSONList;您已经有了一个承诺,只是将其链接在一起。但是,您确实需要处理它不拒绝HTTP的fetch API footgun (只是网络错误):

代码语言:javascript
运行
复制
function fetchJSONList(url) {
    return fetch(url)
        .then(response => {
            if (!response.ok) {
                throw new Error("HTTP error " + response.status);
            }
            return response.json();
        });
}

把这一切加在一起:

代码语言:javascript
运行
复制
let count = {
    1: 0,
    2: 0,
    3: 0,
    4: 0,
    5: 0,
    total: 0
};

let url = {
    1: "https://jsonplaceholder.typicode.com/posts",
    2: "https://jsonplaceholder.typicode.com/comments",
    3: "https://jsonplaceholder.typicode.com/albums",
    4: "https://jsonplaceholder.typicode.com/todos",
    5: "https://jsonplaceholder.typicode.com/users"
};

function fetchJSONList(url) {
    return fetch(url)
        .then(response => {
            if (!response.ok) {
                throw new Error("HTTP error " + response.status);
            }
            return response.json();
        });
}

function checkAll() {
    return Promise.all(Object.entries(url).map(([key, value]) =>
        fetchJSONList(value)
            .then(list => {
                if ($.isEmptyObject(list)) {
                    const spanID = "#api-" + key;
                    $(spanID).text(0);
                }
                $.each(list, function() {
                    count[key]++;
                    count.total++;

                    const spanID = "#api-" + key;
                    $(spanID).text(count[key]);
                });
            })
    ));
}

checkAll()
.then(() => $("#count-total").text(count.total))
.catch(console.log);
代码语言:javascript
运行
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<ul id="site-list">
        <li><span>API 1: </span><span id="api-1">Loading...</span></li>
        <li><span>API 2: </span><span id="api-2">Loading...</span></li>
        <li><span>API 3: </span><span id="api-3">Loading...</span></li>
        <li><span>API 4: </span><span id="api-4">Loading...</span></li>
        <li><span>API 5: </span><span id="api-5">Loading...</span></li>
</ul>
    
<span>Total: </span><span id="count-total">Loading...</span>

如果您想在启动下一个项目之前等待它们中的每一个完成,请使用一个循环构建一个承诺链:

代码语言:javascript
运行
复制
function checkAll() {
    let p = Promise.resolve();
    for (const [key, value] of Object.entries(url)) {
        p = p.then(() => fetchJSONList(value))
            .then(list => {
                if ($.isEmptyObject(list)) {
                    const spanID = "#api-" + key;
                    $(spanID).text(0);
                }
                $.each(list, function() {
                    count[key]++;
                    count.total++;

                    const spanID = "#api-" + key;
                    $(spanID).text(count[key]);
                });
            });
    }
    return p;
}

代码语言:javascript
运行
复制
let count = {
    1: 0,
    2: 0,
    3: 0,
    4: 0,
    5: 0,
    total: 0
};

let url = {
    1: "https://jsonplaceholder.typicode.com/posts",
    2: "https://jsonplaceholder.typicode.com/comments",
    3: "https://jsonplaceholder.typicode.com/albums",
    4: "https://jsonplaceholder.typicode.com/todos",
    5: "https://jsonplaceholder.typicode.com/users"
};

function fetchJSONList(url) {
    return fetch(url)
        .then(response => {
            if (!response.ok) {
                throw new Error("HTTP error " + response.status);
            }
            return response.json();
        });
}

function checkAll() {
    let p = Promise.resolve();
    for (const [key, value] of Object.entries(url)) {
        p = p.then(() => fetchJSONList(value))
            .then(list => {
                if ($.isEmptyObject(list)) {
                    const spanID = "#api-" + key;
                    $(spanID).text(0);
                }
                $.each(list, function() {
                    count[key]++;
                    count.total++;

                    const spanID = "#api-" + key;
                    $(spanID).text(count[key]);
                });
            });
    }
    return p;
}

checkAll()
.then(() => $("#count-total").text(count.total))
.catch(console.log);
代码语言:javascript
运行
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<ul id="site-list">
        <li><span>API 1: </span><span id="api-1">Loading...</span></li>
        <li><span>API 2: </span><span id="api-2">Loading...</span></li>
        <li><span>API 3: </span><span id="api-3">Loading...</span></li>
        <li><span>API 4: </span><span id="api-4">Loading...</span></li>
        <li><span>API 5: </span><span id="api-5">Loading...</span></li>
</ul>
    
<span>Total: </span><span id="count-total">Loading...</span>

或者,如果您的环境支持它们,请使用async函数:

代码语言:javascript
运行
复制
async function checkAll() {
    for (const [key, value] of Object.entries(url)) {
        const list = await fetchJSONList(value);
        if ($.isEmptyObject(list)) {
            const spanID = "#api-" + key;
            $(spanID).text(0);
        }
        $.each(list, function() {
            count[key]++;
            count.total++;

            const spanID = "#api-" + key;
            $(spanID).text(count[key]);
        });
    }
}

代码语言:javascript
运行
复制
let count = {
    1: 0,
    2: 0,
    3: 0,
    4: 0,
    5: 0,
    total: 0
};

let url = {
    1: "https://jsonplaceholder.typicode.com/posts",
    2: "https://jsonplaceholder.typicode.com/comments",
    3: "https://jsonplaceholder.typicode.com/albums",
    4: "https://jsonplaceholder.typicode.com/todos",
    5: "https://jsonplaceholder.typicode.com/users"
};

function fetchJSONList(url) {
    return fetch(url)
        .then(response => {
            if (!response.ok) {
                throw new Error("HTTP error " + response.status);
            }
            return response.json();
        });
}

async function checkAll() {
    for (const [key, value] of Object.entries(url)) {
        const list = await fetchJSONList(value);
        if ($.isEmptyObject(list)) {
            const spanID = "#api-" + key;
            $(spanID).text(0);
        }
        $.each(list, function() {
            count[key]++;
            count.total++;

            const spanID = "#api-" + key;
            $(spanID).text(count[key]);
        });
    }
}

checkAll()
.then(() => $("#count-total").text(count.total))
.catch(console.log);
代码语言:javascript
运行
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<ul id="site-list">
        <li><span>API 1: </span><span id="api-1">Loading...</span></li>
        <li><span>API 2: </span><span id="api-2">Loading...</span></li>
        <li><span>API 3: </span><span id="api-3">Loading...</span></li>
        <li><span>API 4: </span><span id="api-4">Loading...</span></li>
        <li><span>API 5: </span><span id="api-5">Loading...</span></li>
</ul>
    
<span>Total: </span><span id="count-total">Loading...</span>

票数 4
EN

Stack Overflow用户

发布于 2020-07-20 09:25:18

代码语言:javascript
运行
复制
let count = {
    1: 0,
    2: 0,
    3: 0,
    4: 0,
    5: 0,
    total: 0
};

let url = {
    1: "https://jsonplaceholder.typicode.com/posts",
    2: "https://jsonplaceholder.typicode.com/comments",
    3: "https://jsonplaceholder.typicode.com/albums",
    4: "https://jsonplaceholder.typicode.com/todos",
    5: "https://jsonplaceholder.typicode.com/users"
};

function fetchJSONList(url) {
    return new Promise(function(resolve, reject) {
        fetch(url)
            .then(response => { return response.json(); })
            .then(resolve)
            .catch(reject);
    });
}

function checkAll() {
    return new Promise(function(resolve, reject) {
        $.each(url, function(key) {
            fetchJSONList(url[key])
                .then(list => {
                    if ($.isEmptyObject(list)) {
                        const spanID = "#api-" + key;
                        $(spanID).text(0);
                    }
                    $.each(list, function() {
                        count[key]++;
                        count.total++;

                        const spanID = "#api-" + key;
                        $(spanID).text(count[key]);
                        $('#count-total').text(count.total);
                    });
                })
                .catch(reject);
        });
        resolve(count);
    });
}

checkAll();
代码语言:javascript
运行
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<ul id="site-list">
        <li><span>API 1: </span><span id="api-1">Loading...</span></li>
        <li><span>API 2: </span><span id="api-2">Loading...</span></li>
        <li><span>API 3: </span><span id="api-3">Loading...</span></li>
        <li><span>API 4: </span><span id="api-4">Loading...</span></li>
        <li><span>API 5: </span><span id="api-5">Loading...</span></li>
</ul>
    
<span>Total: </span><span id="count-total">Loading...</span>

我的想法是直接在循环中呈现总数。我把你的任务调到循环里了。只调用函数。希望它能成功。

票数 0
EN

Stack Overflow用户

发布于 2020-07-20 10:07:00

你在承诺实现之前就已经解决了。所以解决方案是使用Promise.all

下面的片段可以帮助您(在显示总计之前,我延迟了一秒钟,这样您就可以清楚地看到行为)

代码语言:javascript
运行
复制
let count = {
  1: 0,
  2: 0,
  3: 0,
  4: 0,
  5: 0,
  total: 0
}

let url = {
  1: 'https://jsonplaceholder.typicode.com/posts',
  2: 'https://jsonplaceholder.typicode.com/comments',
  3: 'https://jsonplaceholder.typicode.com/albums',
  4: 'https://jsonplaceholder.typicode.com/todos',
  5: 'https://jsonplaceholder.typicode.com/users'
}

function fetchJSONList(key) {
  return new Promise(function(resolve, reject) {
    fetch(url[key])
      .then(response => {
        return response.json()
      })
      .then(list => resolve([key, list]))
      .catch(reject)
  })
}

function checkAll() {
  return new Promise(function(resolve, reject) {
    Promise.all(Object.keys(url).map(key => fetchJSONList(key)))
      .then(results => {
        results.forEach(([key, list = []]) => {
          if ($.isEmptyObject(list)) {
            const spanID = '#api-' + key
            $(spanID).text(0)
          }
          $.each(list, function() {
            count[key]++
            count.total++

            const spanID = '#api-' + key
            $(spanID).text(count[key])
          })
        })
        
        setTimeout(() => {
          $('#count-total').text(count.total)
          resolve()
        }, 1000)
      })
      .catch(reject)
  })
}

checkAll()
代码语言:javascript
运行
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<ul id="site-list">
        <li><span>API 1: </span><span id="api-1">Loading...</span></li>
        <li><span>API 2: </span><span id="api-2">Loading...</span></li>
        <li><span>API 3: </span><span id="api-3">Loading...</span></li>
        <li><span>API 4: </span><span id="api-4">Loading...</span></li>
        <li><span>API 5: </span><span id="api-5">Loading...</span></li>
</ul>
    
<span>Total: </span><span id="count-total">Loading...</span>

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62992255

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档