当前位置: 首页 > 知识库问答 >
问题:

我试图理解如何在javascript中使用promise,但我的脚本从不执行“Then”

公西宏毅
2023-03-14

我有一个脚本,它设置一组用户名,然后为每个用户名运行一个读取请求,以抽动APIendpoint来获取每个用户的Json信息。然后我想把这些信息放在一个数组中供以后使用,发现我必须使用promise,这是我以前从未使用过的。我读了这个:https://developers.google.com/web/fundamentals/primers/promises和这个:https://github.com/domenic/promises-unwrapping/blob/master/docs/states-and-fates.md,我在这里读到费利克斯·克林的响应:我如何从异步调用返回响应?我仍然无法准确理解什么去了哪里,什么做了什么。这是我到目前为止所拥有的:

var users = ["ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas"]

var arr = [];

var headers = {
  'Client-Id': 'xxxxxxxxxxx'
}

var promise = new Promise(function usersJson(callback) {
  for (i = 0; i < users.length; i++) {
    var url = "https://api.twitch.tv/helix/users?login=" + users[i];
    fetch(url, {headers})
    .then(function(response) {
      return response.json();
    })
    .then(function(myJson) {
      arr.push(myJson);
    })
    callback(arr);
  };
})

promise.then(function(result) {
  console.log(result);
})

据我所知,这应该贯穿每个endpoint,将数据推送到我的数组变量,然后一旦整个事情“实现”,它应该调用带有我的promise变量的“然后”来console.log我的数组。我得到的只是一个空白数组,我真的不确定我做错了什么。如果我把console.log(arr)在arr.push(json)之后,我得到8个数组返回,每个数组都有下一个响应体,所以我知道调用是工作的,我只是不能让它坚持我的阵列。

共有3个答案

胡星汉
2023-03-14

做这样的事情代替:

const runTheTrap = async function(users){
   const ret = [];
   for (i = 0; i < users.length; i++) {
    var url = "https://api.twitch.tv/helix/users?login=" + users[i];
    await fetch(url, {headers})
    .then(function(r) {
      return r.json().then(v => ret.push(v));
    });
  };

  return ret;
}


runTheTrap(users).then(function(result) {
  console.log(result);
});

但坦率地说,异步/等待有点拖沓,我更喜欢这种方法:

     const runTheTrap = function(users){
        return users.map(function(u){
          var url = "https://api.twitch.tv/helix/users?login=" + u;
          return fetch(url, {headers}).then(r => {
              return r.json();
          });
      }



      Promise.all(runTheTrap(users)).then(function(vals){
          // you have your vals
       });
郎子平
2023-03-14

为了得到您想要的结果,您的代码可以重写为

const users = ["ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas"]

const headers = {
  'Client-Id': 'xxxxxxxxxxx'
}

Promise.all(users.map(user => fetch(`https://api.twitch.tv/helix/users?login=${user}`, {headers}).then(response => response.json())))
.then(result => console.log(result));

更具可读性

const users = ["ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas"]

const headers = {
  'Client-Id': 'xxxxxxxxxxx'
}

const mapper = user => 
    fetch(`https://api.twitch.tv/helix/users?login=${user}`, {headers})
    .then(response => response.json());

const promises = users.map(mapper);

Promise.all(promises)
.then(result => console.log(result));

最后,由于您的原始代码显示不了解ES2015

var users = ["ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas"];

var headers = {
    'Client-Id': 'xxxxxxxxxxx'
};

var mapper = function mapper(user) {
    return fetch("https://api.twitch.tv/helix/users?login=" + user, { headers: headers }).then(function (response) {
        return response.json();
    });
};

var promises = users.map(mapper);

Promise.all(promises).then(function (result) {
    return console.log(result);
});
侯和惬
2023-03-14

一种可能帮助你在promise中思考更多的方法是,一旦你在promise之地,你只能在你还在promise之地的时候获得数据。在您的示例中,您从fetchpromise获取数据。这意味着您只能从fetchpromise内部使用该数据。请注意:

.then(function(myJson) {
  arr.push(myJson);
})
callback(arr);

构建阵列的arr.push在promise内部,而callback(arr)在promise外部。因为你已经不在promise范围之内了,所以你无法获得数据。

在您的情况下,您还希望同时等待多个promise,因为您同时从多个源获取数据。最好的方法是使用Promise.all和一组promise:

const promise = Promise.all(users.map(user => {
    const url = `https://api.twitch.tv/helix/users?login=${user}`;
    return fetch(url, { headers })
    .then(function(response) {
      return response.json();
    });
}));

现在,promise。然后,将允许您在解决所有promise后访问一组数据。您不需要推送到另一个数组,。map将为您创建一系列promise。

您还可以使用async/await语法编写此代码,该语法更易于推理,而且可能更简洁。

const promise = Promise.all(users.map(async user => {
    const url = `https://api.twitch.tv/helix/users?login=${user}`;
    const response = await fetch(url, { headers });
    return response.json();
}));

顺便说一句,当使用本身不实现promise的库时,您应该只需要使用newpromisefetch已经返回了一个promise,所以当你调用它时,你已经得到了一个promise,所以没有必要用new Promise来包装它。

 类似资料:
  • 是否有可能在函数的上下文中解析(实现)一个promise对象?是否有其他方法处理这个问题? UPD:这个代码对我有效。谢了!

  • 新手,大佬轻点喷,vue2项目,搜索框用的原生,请求数据用的axios 我在项目中写了一个搜索框,目前数据的静态的,我想动态获取数据,但数据是异步请求获取的,如果我像下面直接这样赋值会获取不到值,我想使用promise改写,请问以下应当如何改写 代码:

  • 问题内容: 我正在写一个如下的shell脚本: 现在,我想要实现的是列出$ ACTIONS_DIR中的每个文件以执行该文件。$ ACTIONS_DIR下的每个文件都是另一个Shell脚本。 现在,这里的问题在于,使用exec之后,脚本将停止并且不会转到下一个文件。任何想法为什么会这样? 问题答案: 替换shell进程。如果只想将该命令作为子进程调用,则将其删除。

  • 问题内容: 我希望服务器每分钟执行一次节点脚本。如果我手动执行文件(),该程序将完美执行,因此,我很确定这不是问题。但是,当我将其交给cron执行时,什么也没发生。 这是cron文件中的行。 这是一个示例日志: 可执行文件: 知道我为什么要广播静音吗?我应该在其他地方调试? 更新: 我相信问题与我的相对文件路径有关,并且main.js从其自己的目录外部执行。 所以现在,我已经放置在目录中。看起来像

  • 它涵盖了哪些用例?何时应该使用而不是常规的? 这个问题与硒有关,但与语言无关。

  • 问题内容: 如何在Linux中从C执行Shell脚本? 问题答案: 这取决于您要对脚本(或要运行的任何其他程序)执行的操作。 如果只想运行脚本,这是最容易的事情,但是它也做其他一些事情,包括运行shell并让其运行命令(在大多数* nix下是/ bin / sh)。 如果您要通过标准输入来输入shell脚本或使用其标准输出,则可以使用(和)设置管道。这也使用外壳程序(大多数* nix下是/ bin