【问题标题】:Access value that promise .then returns outside of promise访问承诺的值。然后在承诺之外返回
【发布时间】:2017-04-05 00:05:26
【问题描述】:

标题说明了一切,我使用的是async-libraryeachSeries方法

let 
  valueOne = null,
  validItem = null;

const asyncEachSeries = require('async/eachSeries');

const getContent = function (item) {
  contentResponse = fetchContent(item);
  return contentResponse;
}

if (recommendationsArr.length > 0) {
  asyncEachSeries(recommendationsArr, function (item, callback) {
    getApiContent(item).then(function getValidResult(response) {
      try { 
        valueOne = response.content.valueOne || null; //may or may not be present
        recommendationsArr.splice(recommendationsArr.indexOf(item), 1); 
        validItem = item;
        console.log("##### valueOne is: ", valueOne); // I get data here
        return true;
      } catch (err) {
        valueOne = null;
        return false;
      }
    });
    //I am guessing I need a return statement here, though not sure what
  });

  console.log("##### Outside promise, valueOne is: ", valueOne); // no data here

  // Access valueOne, validItem, recommendationsArr to be able to pass as props for the component 
  return {
    component: <Layout><ComponentName
      //pass other non-dependent props
      validItem={validItem}
      valueOne={valueOne}
      recommendationsArr={recommendationsArr}
    /></Layout>,
    title: `Page Title`,
  };
}

return null;

场景:recommendationsArr 是一个项目数组(它的 99.9% 不为空,但由于它是一个外部 api 调用,我更喜欢检查)。目的是为valueOnevalidItem 和更新的recommendationsArr 提供值。
有效性取决于valueOne 的存在,所以如果recommendationsArr[0] 具有有效的valueOne,那么我不需要为数组的其余部分获取api 结果。我正在使用eachSeries,因为它一次只运行一个异步操作,因此如果该异步为我提供了有效的结果,我不必遍历其他项目。

样品推荐Arr:recommendationsArr = ["blue", "white", "green", "red"]; //usually the array is anywhere between 12-50 elements

现在,为了能够将更新后的值传递给组件,我需要能够在 asyncEachSeries 迭代循环之外访问在 try 块中设置的值。我知道我将不得不return 处理过的/新的值,但不确定在什么时候以及如何返回这些值。

【问题讨论】:

  • 您是否在任何地方使用var 初始化 valueOne?如果没有,请尝试将var valueOne; 放在承诺之上
  • 你不能指望 valueOne 在那个时候有一个值,因为异步代码是异步的 - 再多的回报也无济于事
  • 不确定异步,但 bluebirds .mapSeries 将解析一组值。
  • @fredrover 我愿意,我在承诺上方有一个let,刚刚更新了问题
  • @Matt 我不确定我是否理解你的意思,我能够遍历数组,挑战是访问承诺之外的值

标签: javascript node.js promise react-redux


【解决方案1】:

与任何有关异步代码的问题一样,您可以使用callback 返回值。但是eachSeries 不收集返回值。你要的是async.mapSeries:

async.mapSeries(recommendationsArr, function (item, callback) {
  getApiContent(item).then(function (response) {
    try { 
      valueOne = response.content.valueOne || null; //may or may not be present
      recommendationsArr.splice(recommendationsArr.indexOf(item), 1); 
      validItem = item;
      callback(null, valueOne); // This is how you return a value
      // return true; // return does absolutely nothing
    } catch (err) {
      valueOne = null;
      callback(err, valueOne);
      // return false;
    }
  });
},function (err, result) {
  // this is where you can process the result
  // note that the result is an array
});

但是,由于您使用的是 Promise,因此您可以使用 async-q 代替它将 caolan 的异步库包装在 Promise 中:

var asyncQ = require('async-q');

asyncQ.mapSeries(recommendationsArr, function (item) {
  // Note: the return in the line below is important
  return getApiContent(item).then(function (response) {
    try { 
      valueOne = response.content.valueOne || null; //may or may not be present
      recommendationsArr.splice(recommendationsArr.indexOf(item), 1); 
      validItem = item;
      return valueOne; // this is how you return a value in a promise
    } catch (err) {
      return null
    }
  });
})
.then(function(result) {
  // you can process the result here
});

我个人更喜欢重写代码并在最后处理结果,因为代码更干净:

asyncQ.mapSeries(recommendationsArr, getApiContent)
  .then(function (result) {
    for(var i=0;i<result.length;i++) {
      var response = result[i];
      // do what needs to be done with each response here
    }
  });

【讨论】:

  • asyncQ.mapSeries 不是同步的,原因是使用 async-library eachSeries 方法,因为它一次只运行一个异步操作,因为我不需要遍历整个数组我只关心第一个最佳匹配,我如何使用mapSeries 实现?
  • mapSeries 与 eachSeries 完全相同,只是最终回调也传递了操作的最终结果。阅读文档
  • @user988544: async.eachSeries 将遍历整个数组
  • @user988544:也许最好解释一下你认为你想要做什么,而不是你认为你的代码有什么问题
猜你喜欢
  • 1970-01-01
  • 2016-09-18
  • 1970-01-01
  • 1970-01-01
  • 2023-01-27
  • 2016-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多