Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/388.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/40.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在循环中等待承诺 let-currentProduct; 对于(设i=0;i{ 更新(潜艇、当前产品); }); }_Javascript_Node.js_Promise_Async Await_Bluebird - Fatal编程技术网

Javascript 在循环中等待承诺 let-currentProduct; 对于(设i=0;i{ 更新(潜艇、当前产品); }); }

Javascript 在循环中等待承诺 let-currentProduct; 对于(设i=0;i{ 更新(潜艇、当前产品); }); },javascript,node.js,promise,async-await,bluebird,Javascript,Node.js,Promise,Async Await,Bluebird,我使用的是蓝鸟,方法是getAll和update返回承诺。我怎么能说“等到两个承诺返回,然后更新currentProduct值”?我对JS非常陌生…如果您可以使用async/wait,这将非常简单: let currentProduct; for (let i = 0; i < products.length; i++) { currentProduct = products[i]; subscription.getAll(products[i]._id)

我使用的是蓝鸟,方法是getAllupdate返回承诺。我怎么能说“等到两个承诺返回,然后更新currentProduct值”?我对JS非常陌生…

如果您可以使用
async
/
wait
,这将非常简单:

let currentProduct;

for (let i = 0; i < products.length; i++) { 
    currentProduct = products[i];

    subscription.getAll(products[i]._id)
        .then((subs) => {
            update(subs, currentProduct);
        });
}
在第二个代码段中,循环只设置整个链,但不执行
中的代码。然后立即执行
。您的
getAll
函数将不会运行,直到前一个函数依次解决(这是您想要的)。

以下是我的方法:

let currentProduct;

let promiseChain = Promise.resolve();
for (let i = 0; i < products.length; i++) { 
    currentProduct = products[i];

    // Note that there is a scoping issue here, since
    // none of the .then code runs till the loop completes,
    // you need to pass the current value of `currentProduct`
    // into the chain manually, to avoid having its value
    // changed before the .then code accesses it.

    const makeNextPromise = (currentProduct) => () => {
        // Make sure to return your promise here.
        return subscription.getAll(products[i]._id)
            .then((subs) => {
                // Make sure to return your promise here.
                return update(subs, currentProduct);
            });
    }

    // Note that we pass the value of `currentProduct` into the
    // function to avoid it changing as the loop iterates.
    promiseChain = promiseChain.then(makeNextPromise(currentProduct))
}

无需手动通过索引链接承诺或迭代数组:)

您可能希望跟踪已处理的产品,因为当一个产品失败时,您不知道有多少成功,也不知道要更正(如果回滚)或重试什么

异步“循环”可以是递归函数:

for (let product of products) { 
  let subs = await subscription.getAll(product._id);
  await update(subs, product);
}
如果没有异步,则可以使用递归或reduce:

const updateProducts = /* add async */async (products,processed=[]) => {
  try{
    if(products.length===0){
      return processed;
    }
    const subs = await subscription.getAll(products[0]._id)
    await update(subs, product);
    processed.push(product[0]._id);  
  }catch(err){
    throw [err,processed];
  }
  return await updateProducts(products.slice(1),processed);
}
以下是如何调用updateProducts:

//using reduce
const updateProducts = (products) => {
  //keep track of processed id's
  const processed = [];
  return products.reduce(
    (acc,product)=>
      acc
      .then(_=>subscription.getAll(product._id))
      .then(subs=>update(subs, product))
      //add product id to processed product ids
      .then(_=>processed.push(product._id)),
    Promise.resolve()
  )
  //resolve with processed product id's
  .then(_=>processed)
  //when rejecting include the processed items
  .catch(err=>Promise.reject([err,processed]));
}

//using recursion
const updateProducts = (products,processed=[]) =>
  (products.length!==0)
    ? subscription.getAll(products[0]._id)
      .then(subs=>update(subs, product))
      //add product id to processed
      .then(_=>processed.push(products[0]._id))
      //reject with error and id's of processed products
      .catch(err=>Promise.reject([err,processed]))
      .then(_=>updateProducts(products.slice(1),processed))
    : processed//resolve with array of processed product ids

为什么这个问题被标记为async Wait?是否要使用此功能?如果使用
wait
,您也会使用它而不是
then
call@Bergi你说得对。您可以使用wait获得
getAll
的结果,然后将其传递给下一行的
update
,并使用另一个wait。但是那里的东西仍然是有效的,我已经知道混合和匹配我的等待,然后。我会说,这取决于OP的判断,他更喜欢哪种风格。@Jumpa我编辑了这篇文章,以包含一对等待的示例,请参见第一个片段中的注释部分。承诺链使用递归将是最简单的,而使用reduce则不那么简单(请参见我的答案)。这个答案也会解决或拒绝一些正常的东西,特别是当你需要知道它走了多远而被拒绝时。@neustart47因为每个“then”链都是最后一个,只需在循环完成后将它添加到承诺链的
。然后
。例如,在循环之后:
promiseChain。然后(()=>{/*做你的事*/})
我在尝试你的代码,我认为这是更优雅的代码。无论如何,在for中缺少产品的“let”。我注意到,因为我收到一个未处理的PromiserEjectionWarning…您能编辑您的代码并添加一些内容来处理拒绝承诺吗?非常感谢。编辑:无论如何我应该使用try/catch。。。
//using reduce
const updateProducts = (products) => {
  //keep track of processed id's
  const processed = [];
  return products.reduce(
    (acc,product)=>
      acc
      .then(_=>subscription.getAll(product._id))
      .then(subs=>update(subs, product))
      //add product id to processed product ids
      .then(_=>processed.push(product._id)),
    Promise.resolve()
  )
  //resolve with processed product id's
  .then(_=>processed)
  //when rejecting include the processed items
  .catch(err=>Promise.reject([err,processed]));
}

//using recursion
const updateProducts = (products,processed=[]) =>
  (products.length!==0)
    ? subscription.getAll(products[0]._id)
      .then(subs=>update(subs, product))
      //add product id to processed
      .then(_=>processed.push(products[0]._id))
      //reject with error and id's of processed products
      .catch(err=>Promise.reject([err,processed]))
      .then(_=>updateProducts(products.slice(1),processed))
    : processed//resolve with array of processed product ids
updateProducts(products)
.then(processed=>console.log("Following products are updated.",processed))
.catch(([err,processed])=>
  console.error(
    "something went wrong:",err,
    "following were processed until something went wrong:",
    processed
  )
)