Jump to content
  • Hello visitors, welcome to the Hacker World Forum!

    Red Team 1949  (formerly CHT Attack and Defense Team) In this rapidly changing Internet era, we maintain our original intention and create the best community to jointly exchange network technologies. You can obtain hacker attack and defense skills and knowledge in the forum, or you can join our Telegram communication group to discuss and communicate in real time. All kinds of advertisements are prohibited in the forum. Please register as a registered user to check our usage and privacy policy. Thank you for your cooperation.

    TheHackerWorld Official

使用 JavaScript Promise 读取 Github 某用户的数据

 Share


KaiWn

Recommended Posts

    • 代码如下:

      // Make a request for user.json
      fetch('/article/promise-chaining/user.json')
        // Load it as json
        .then(response => response.json())
        // Make a request to GitHub
        .then(user => fetch(`https://api.github.com/users/${user.name}`))
        // Load the response as json
        .then(response => response.json())
        // Show the avatar image (githubUser.avatar_url) for 3 seconds (maybe animate it)
        .then(githubUser => {
          let img = document.createElement('img');
          img.src = githubUser.avatar_url;
          img.className = "promise-avatar-example";
          document.body.append(img);
      
          setTimeout(() => img.remove(), 3000); // (*)
        });

      这里的语义比较清楚,每一个 then 调用都返回一个 Promise,后续的 then 调用,必须在前一个 then 调用返回的 Promise 被 resolve 之后,才能得到执行。

      不过上述代码有一个缺陷:

      看 * 所在行的代码:在头像完成显示并被移除后,如果我们想添加一些额外的处理逻辑,应该怎么做? 例如,我们想显示一个用于编辑该用户或其他内容的表单。

      为了使链可扩展,我们需要返回一个在头像完成显示时进行 resolve 的 Promise.

      代码如下:

      fetch('/article/promise-chaining/user.json')
        .then(response => response.json())
        .then(user => fetch(`https://api.github.com/users/${user.name}`))
        .then(response => response.json())
        .then(githubUser => new Promise(function(resolve, reject) { // (*)
          let img = document.createElement('img');
          img.src = githubUser.avatar_url;
          img.className = "promise-avatar-example";
          document.body.append(img);
      
          setTimeout(() => {
            img.remove();
            resolve(githubUser); // (**)
          }, 3000);
        }))
        // triggers after 3 seconds
        .then(githubUser => alert(`Finished showing ${githubUser.name}`));

      也就是说,(*) 行中的 .then 处理程序现在返回新的 Promise,该 Promise 仅在 setTimeout (**) 中的 resolve(githubUser) 调用后才被解决。 链中的下一个 .then 将等待它。

      下图第 5 行新建的 Promise 对象,这个对象在第 13 行会 resolve,这个 resolve 操作,会触发等待它的第 17 行的 then 方法。
      cc3d2c3ac5c6c542820d583842167829.png

      作为一种好的实践,异步操作应始终返回一个 Promise. 这使得在它之后的计划行动成为可能;即使我们现在不打算扩展链,我们以后也可能需要它。

      最后我们对代码进行重构。

      function loadJson(url) {
        return fetch(url)
          .then(response => response.json());
      }

      以上的函数返回一个 Promise,当 response 的 json 数据可用时,这个 promise 后注册的 .then 函数就会触发。

      看其消费代码:

      a675d54b4eb850ffb8ef14d67aea3126.png

      26 行 then 里的箭头函数触发时,user 就是 25 行 user.json 数据被反序列化之后形成的 JSON 对象。

      function loadGithubUser(name) {
        return loadJson(`https://api.github.com/users/${name}`);
      }

      只是对 loadJson 的一层封装,让调用者不需要知道 Github user api 具体的 endpoint.

      function showAvatar(githubUser) {
        return new Promise(function(resolve, reject) {
          let img = document.createElement('img');
          img.src = githubUser.avatar_url;
          img.className = "promise-avatar-example";
          document.body.append(img);
      
          setTimeout(() => {
            img.remove();
            resolve(githubUser);
          }, 3000);
        });
      }

      返回一个 Promise,在其 executor 里书写业务逻辑,并通过 resolve(githubUser) 将 Promise 状态设置为 fulfilled,方便将来的扩展。

      最后的完整代码:

      // Use them:
      loadJson('/article/promise-chaining/user.json')
        .then(user => loadGithubUser(user.name))
        .then(showAvatar)
        .then(githubUser => alert(`Finished showing ${githubUser.name}`));
        // ...

      总结

      如果 .then(或 catch/finally,无关紧要)处理程序返回一个 Promise,则 Promise 链的其余部分会一直等待,直到这个 pending 的 Promise 被 resolve. 当 Promise 内部的 executor 有数据被 resolve 调用时,resolve 输入的数据(或错误)会被进一步传递到 Promise chain 里的其他 Promise.then 中去。

      fee42118792d2e61b0b138635d6a88e9.png

Link to post
Link to comment
Share on other sites

 Share

discussion group

discussion group

    You don't have permission to chat.
    • Recently Browsing   0 members

      • No registered users viewing this page.
    ×
    ×
    • Create New...