javascript – 如何在拒绝上链接承诺

给定一个函数,fn,它返回一个promise,以及一个任意长度的数据数组(例如data = [‘apple’,’orange’,’banana’,…])你如何在每个元素上链接函数调用数组按顺序排列,如果fn(data [i])解析,整个链完成并停止调用fn,但如果fn(data [i])拒绝,则执行下一个调用fn(data [i 1])?

这是一个代码示例:

// this could be any function which takes input and returns a promise
// one example might be fetch()
const fn = datum =>
  new Promise((resolve, reject) => {
    console.log(`trying ${datum}`);

    if (Math.random() < 0.25) {
      resolve(datum);
    } else {
      reject();
    }
  });

const foundResult = result => {
  // result here should be the first value that resolved from fn(), and it
  // should only be called until the first resolve()
  console.log(`result = ${result}`);
};

// this data can be purely arbitrary length
const data = ['apple', 'orange', 'banana', 'pineapple', 'pear', 'plum'];

// this is the behavior I'd like to model, only for dynamic data
fn('apple').then(foundResult)
  .catch(() => {
    fn('orange').then(foundResult)
      .catch(() => {
        fn('banana').then(foundResult)
          .catch(() => {
            /* ... and so on, and so on ... */
          });
      });
  });

我觉得也许这种模式的优雅解决方案是我所缺少的.这个行为与Array.some()非常相似,但是我试图摆弄它是空洞的.

编辑:我从数字数据切换到字符串,以强调解决方案不需要依赖于数字数据.

编辑#2:为了进一步澄清,fn可以是任何接受输入并返回promise的函数.上面的fn实现只是为了给出一个完整的例子.实际上,fn实际上可能类似于API请求,数据库查询等.

最佳答案
您可以使用async / await和循环:

async function search() {
  for (let item of data) {
    try {
      return await fn(item);
    } catch (err) { }
  }
  throw Error ("not found"); 
}

search().then(foundResult).catch(console.log);

> fn可以返回Promise(等待)或只返回一个值(返回)
>您的数据可能是无限可迭代序列(生成器)
>在我看来,它也易于阅读和理解意图.

如果序列失败,这是输出:

trying apple
trying orange
trying banana
trying pineapple
trying pear
trying plum
Error: not found

异步的支持在es2017中是原生的,但可以用babeltypescript转换为es3 / es5

转载注明原文:javascript – 如何在拒绝上链接承诺 - 代码日志