【问题标题】:Using Fetch API with Promise.all将 Fetch API 与 Promise.all 一起使用
【发布时间】:2017-11-25 09:04:16
【问题描述】:

我的目标是从两个 URL 获取数据并仅在两个 URL 都成功返回时执行操作。另一方面,如果其中任何一个失败,我想返回一个错误。我已经玩弄了我的代码并设法获得了预期的效果。

我的问题是,是否有更有效、更简洁的方法来实现相同的功能?

辅助函数

let status = (r) => {  
  if (r.ok) {  
    return Promise.resolve(r)  
  } else {  
    return Promise.reject(new Error(r.statusText))  
  }  
}

let json = (r) => r.json();

请求

let urls = [
    'http://localhost:3000/incomplete',
    'http://localhost:3000/complete'
]

let promises = urls.map(url => {

    return fetch(url)  
    .then(status)  
    .then(json)  
    .then(d => Promise.resolve(d))
    .catch(e => Promise.reject(new Error(e)));

});

Promise.all(promises).then(d => {
    // do stuff with d
}).catch(e => {
    console.log('Whoops something went wrong!', e);
});

【问题讨论】:

  • 如果您的代码有效,那么codereview.stackexchange.com 可能是一个更好的提问地点。乍一看,.then(d => Promise.resolve(d)).catch(e => Promise.reject(new Error(e))); 行似乎没有必要(它们不会做任何不会发生的事情)。 status 函数也可以是 if (r.ok) { return r; } else {throw new Error(r.statusText); }。无需在不需要的地方创建承诺。
  • 在你的地图函数内部不要调用“then”,喜欢的只是返回 fetch(url)
  • @FelixKling 谢谢!我不知道该网站存在!太棒了,我把那条线减少到let promises = urls.map(url => fetch(url).then(status).then(json));
  • @PaulOkeke 如果我只是在map 中返回fetch(url),那么我如何检查我的回复是否正常?
  • @Samuel 您将检查 Promises.all 中的所有响应。例如 Promises.all (promises).then(allfetch => { allfetch [0], allfetch [1].... }) 。 Promise.all 将自动调用所有 Promise 上的“then”函数,并且所有 Promise 的结果都以数组的形式返回,按照它们添加的顺序。我目前正在用手机打字……您可以查看文档。 developer.mozilla.org/en/docs/Web/JavaScript/Reference/…

标签: javascript ajax ecmascript-6 es6-promise fetch-api


【解决方案1】:

使用 fetchOk 获得更好的错误消息,使用 destructuring 访问结果:

let fetchOk = (...args) => fetch(...args)
  .then(res => res.ok ? res : res.json().then(data => {
    throw Object.assign(new Error(data.error_message), {name: res.statusText});
  }));

Promise.all([
  'http://localhost:3000/incomplete',
  'http://localhost:3000/complete'
].map(url => fetchOk(url).then(r => r.json()))).then(([d1, d2]) => {
  // do stuff with d1 and d2
}).catch(e => console.error(e));


// Work around stackoverflow's broken error logger.
var console = { error: msg => div.innerHTML += msg + "<br>" };
&lt;div id="div" style="white-space: pre;"&gt;&lt;/div&gt;

【讨论】:

  • 我看不出这比 OP 已经拥有的“更有效或更简洁的方式”。此外,OP 不想在错误情况下调用 .json()
  • @Bergi 错误消息是 JSON 格式。你不想知道出了什么问题吗? - 我认为大多数人更喜欢一个 fetch 函数,它会抛出 not-ok,并抛出一个信息错误。否则我们最终不得不记住在每次提取时检查状态,这很容易出错。这是一种更好的重用模式,更简洁。
  • 你怎么知道错误信息是 JSON 格式的?据我们所知,OP 要求提供与他已经拥有的功能相同的代码。
  • @Bergi OP 期望 json 成功,并希望 !r.ok 抛出错误,所以我假设任何错误消息也会在 json 中。这不常见吗? OP 的示例实际上并没有演示此失败路径,但是当我 Run code snippet 在我的 other answer 中时,这似乎有效。
【解决方案2】:

// https://jsonplaceholder.typicode.com - Provides test JSON data
var urls = [
  'https://jsonplaceholder.typicode.com/todos/1',
  'https://jsonplaceholder.typicode.com/todos/2',
  'https://jsonplaceholder.typicode.com/posts/1',
  'https://jsonplaceholder.typicode.com/posts/2'
];

// Maps each URL into a fetch() Promise
var requests = urls.map(function(url){
  return fetch(url)
  .then(function(response) {
// throw "uh oh!";  - test a failure
return response.json();
  })  
});

// Resolve all the promises
Promise.all(requests)
.then((results) => {
  console.log(JSON.stringify(results, null, 2));
}).catch(function(err) {
  console.log("returns just the 1st failure ...");
  console.log(err);
})
&lt;script src="https://getfirebug.com/firebug-lite-debug.js"&gt;&lt;/script&gt;

【讨论】:

    【解决方案3】:
    const urls = [
        'http://localhost:3000/incomplete',
        'http://localhost:3000/complete'
    ]
    const json = (r) => r.json()
    const status = (r) => r.ok ? Promise.resolve(r) : Promise.reject(new Error(r.statusText))
    const toRequest = url => fetch(url).then(status).then(json)
    const onError = e => { console.log('Whoops something went wrong!', e) }
    const consumeData = data => { console.log('data: ', data) }
    
    Promise.all(urls.map(toRequest))
      .then(consumeData)
      .catch(onError)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-03-14
      • 1970-01-01
      • 2017-09-29
      • 1970-01-01
      • 2021-06-11
      • 2019-05-27
      • 1970-01-01
      • 2021-02-17
      相关资源
      最近更新 更多