javascript - 不知道如何在 react 中处理这个问题 - 多个 promise

标签 javascript json reactjs callback promise

因此,解释这一点的最简单方法是,我尝试在 package.json 中搜索所有包,然后使用 npm 注册表查看是否有新更新。我已经完成了大部分工作。接受以下 for 循环:

import request from 'request'

export const findAllUpdates = (packageInfo) => {
  for(prop in packageInfo) {
    request('https://registry.npmjs.org/' + prop, function(err, resp) {
      json = JSON.parse(resp.body);

      if (json['dist-tags'].latest !== packageInfo[prop].version) {
        // Do something, we are not the same version so we should 
        // update some counter.
      }
    });
  }
}

您的 packageInfokey=>value 的对象,它表示 package.json 和 package-lock.json 的依赖项或开发依赖项或 yarn .lock

重要的部分是我们在上面的函数中查看您安装的内容,然后我们使用注册表获取该软件包信息并将注册表上的最新版本与您安装的版本进行比较,然后我们想要理想情况下,用总计数更新组件的状态。

问题是我们已经进入了回调 hell ,尤其是使用 for 循环,循环遍历每个包,发出请求。

我无法创建变量并将响应存储在其中,因为发出请求后无法访问它。我看不出在这里使用事件是如何工作的,因为您可能安装了 40 个作为 dep 或 dev 的包,这需要触发很多事件。

最后,正确的解决方案可能是使用 Promise,但 Promise 的整个概念是使用 .then(() => {}).catch( () => {}) 这让我回到了第一个方向。

目标是在组件中调用此方法,并使用必须更新的包总数(或至少有新版本)来更新该组件的状态

有什么想法吗?难道我的做法全错了?

最佳答案

您关注 promise 是正确的。

第一件事是给自己一个启用 Promise 的 request 版本。有一个promisify util 中的函数采用 Node 回调样式函数并返回启用 Promise 的版本。所以:

import util from 'util';
// ...
const prequest = util.promisify(request);

(还有一个 npm 模块 promisify ,它可以一次性执行整个 API。)

然后,执行您的请求,将 Promise 收集到一个数组中(并对它们使用 then 进行任何后处理;then 返回一个新的 Promise,所以我们仍然很好),并使用 Promise.all 等待它们全部解决(或其中任何一个拒绝);

所以大家在一起:

import request from 'request';
import util from 'util';

const prequest = util.promisify(request);

export const findAllUpdates = (packageInfo) => {
  const updates = []
  for (const prop in packageInfo) {
    updates.push(prequest('https://registry.npmjs.org/' + prop).then(resp => {
      const json = JSON.parse(resp.body);

      if (json['dist-tags'].latest !== packageInfo[prop].version) {
        // Do something, we are not the same version so we should 
        // update some counter.
      }

      // Perhaps return something here, it will be the resolution
      // for the promise for this request; otherwise, the promise
      // will resolve with `undefined`.
    }));
  }
  return Promise.all(updates);
};

整个函数的 Promise 将解析为数组中每个 Promise 的结果数组(按顺序),或者(再次)如果其中任何一个拒绝,则拒绝。

我希望能够建议async/await,但它目前并没有为一堆并行的 promise 带来太多好处。 (偶尔有人会说 await.all 可以实现 Promise.all 的功能,但[还没有流行起来?]。)

话虽如此,如果我们稍微分解一下,使用 async/await 会更好一些:

import request from 'request';
import util from 'util';

const prequest = util.promisify(request);

const checkOne = async (prop) => {
  const resp = await prequest('https://registry.npmjs.org/' + prop);
  const json = JSON.parse(resp.body);
  if (json['dist-tags'].latest !== packageInfo[prop].version) {
    // Do something, we are not the same version so we should 
    // update some counter.
  }

  // Perhaps return something here, it will be the resolution
  // for the promise for this request; otherwise, the promise
  // will resolve with `undefined`.
};

export const findAllUpdates = (packageInfo) => {
  const updates = []
  for (const prop in packageInfo) {
    updates.push(checkOne(prop);
  }
  return Promise.all(updates);
};

当然,如果 packageInfo 中的所有属性都是“自己的”属性(不是继承的),findAllUpdates 会变得更简单:

export const findAllUpdates = (packageInfo) => {
  return Promise.all(Object.keys(packageInfo).map(checkOne));
};
<小时/>

旁注:我在上面添加了一些缺少的声明。

关于javascript - 不知道如何在 react 中处理这个问题 - 多个 promise ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47335755/

相关文章:

javascript - 异步请求后数组中 undefined index

c# - 序列化并忽略抛出异常的属性

javascript - componentDidMount 不渲染

javascript - 如何在 ruby​​ on Rails 中将文本值迭代为 Active Record 模型名称格式?

javascript - 所有元素都采用相同的值

javascript - knockout.js 中第一列和最后一列之间具有动态列的表

javascript - Redux React 从 API 创建初始状态

javascript - HTML5 Canvas - 与球物理故障的碰撞

c# - 当没有字段名称时反序列化json字符串。在c#中

node.js - React-native 和 Redux 健康的方式来调用 props 变化的 Action