等到所有诺言都完成,即使有些诺言被拒绝


404

假设我有一组Promise正在发出网络请求的,其中一个会失败:

// http://does-not-exist will throw a TypeError
var arr = [ fetch('index.html'), fetch('http://does-not-exist') ]

Promise.all(arr)
  .then(res => console.log('success', res))
  .catch(err => console.log('error', err)) // This is executed   

假设我要等到所有这些完成为止,无论是否失败。我可能无法使用的资源可能会出现网络错误,但是如果可以得到,我会在继续之前希望这样做。我想优雅地处理网络故障。

既然Promises.all没有任何余地,那么在不使用Promise库的情况下,推荐的处理方式是什么?


对于拒绝的诺言,应在结果数组中返回什么?
库巴Wyrostek

9
ES6 Promise不支持这种方法(并且目前显然比Bluebird慢)。另外,并不是所有的浏览器或引擎现在都支持它们。我强烈建议您使用Bluebird,它allSettled可以满足您的需求,而您无需自己动手。
丹·潘特里

@KubaWyrostek我认为您提出Promise.all没有这种行为的原因,我认为这是有道理的。这不是它的工作方式,但是另一种观点是说Promise.all应该返回一个永不失败的特殊承诺-并且您将得到作为代表失败的承诺的参数抛出的错误。
内森·哈根

要添加Dan共享的内容,可以通过“ reflect”功能来使用bluebird所具有的allSettled / stantAll之类的功能。
user3344977

2
@Coli:嗯,我不这么认为。Promise.all会在任何一个诺言被拒绝后立即拒绝,因此您提议的惯用语不能保证所有诺言都得到解决。
约尔格W¯¯米塔格

Answers:


308

更新,您可能要使用内置的native Promise.allSettled

Promise.allSettled([promise]).then(([result]) => {
   //reach here regardless
   // {status: "fulfilled", value: 33}
});

有趣的是,下面的回答是将这种方法添加到语言中的现有技术:]


当然,您只需要一个reflect

const reflect = p => p.then(v => ({v, status: "fulfilled" }),
                            e => ({e, status: "rejected" }));

reflect(promise).then((v => {
    console.log(v.status);
});

或使用ES5:

function reflect(promise){
    return promise.then(function(v){ return {v:v, status: "fulfilled" }},
                        function(e){ return {e:e, status: "rejected" }});
}


reflect(promise).then(function(v){
    console.log(v.status);
});

或在您的示例中:

var arr = [ fetch('index.html'), fetch('http://does-not-exist') ]

Promise.all(arr.map(reflect)).then(function(results){
    var success = results.filter(x => x.status === "fulfilled");
});

3
我认为这是一个很好的解决方案。您可以修改它以包含更简单的语法吗?问题的症结在于,如果您要处理子承诺中的错误,则应捕获它们并返回错误。因此,例如: gist.github.com/nhagen/a1d36b39977822c224b8
内森·哈根

3
@NathanHagen它使您可以找出哪些被拒绝和哪些被满足,然后将问题提取给可重用的运算符。
本杰明·格林鲍姆

4
针对我自己的问题,我创建了以下npm软件包: github.com/Bucabug/promise-reflect npmjs.com/package/promise-reflect
SamF

2
不久前,我遇到了这个问题,并为此创建了一个npm软件包:npmjs.com/package/promise-all-soft-fail
velocity_distance

5
这个词reflect在计算机科学中是常见词吗?您能否链接到维基百科之类的解释内容。我一直在努力寻找,Promise.all not even first reject但不知道要搜索“反映”。ES6是否应该有一个Promise.reflect类似于“ Promise.all但实际上全部”的?
Noitidart '18

253

类似的答案,但对于ES6可能更惯用:

const a = Promise.resolve(1);
const b = Promise.reject(new Error(2));
const c = Promise.resolve(3);

Promise.all([a, b, c].map(p => p.catch(e => e)))
  .then(results => console.log(results)) // 1,Error: 2,3
  .catch(e => console.log(e));


const console = { log: msg => div.innerHTML += msg + "<br>"};
<div id="div"></div>

根据类型的值(一个或多个)返回时,往往可以区分错误很轻松了(如使用undefined了“不关心”,typeof对于普通的非对象值result.messageresult.toString().startsWith("Error:")等等)


1
@KarlBateman我认为你很困惑。顺序函数的解析或拒绝在这里无关紧要,因为该.map(p => p.catch(e => e))部件会将所有拒绝都转换为已解析的值,因此Promise.all无论单个函数解析还是拒绝,无论它们花费多长时间,都仍要等待一切完成。尝试一下。
三角帆

39
.catch(e => console.log(e));从来没有被称为,因为这永远不会失败
fregante

4
@ bfred.it是正确的。虽然终止承诺链catch通常是好的做法,恕我直言
三角帆

2
@SuhailGupta它捕获错误e并将其作为常规(成功)值返回。与p.catch(function(e) { return e; })仅短短相同。return是隐式的。
三角帆

1
@JustinReusnow已经在评论中提及。总是好的做法是终止链,以防日后添加代码。
三角帆

71

本杰明的答案为解决此问题提供了一个很好的抽象,但是我希望有一个不太抽象的解决方案。解决此问题的明确方法是简单地调用.catch内部promise,然后从其回调中返回错误。

let a = new Promise((res, rej) => res('Resolved!')),
    b = new Promise((res, rej) => rej('Rejected!')),
    c = a.catch(e => { console.log('"a" failed.'); return e; }),
    d = b.catch(e => { console.log('"b" failed.'); return e; });

Promise.all([c, d])
  .then(result => console.log('Then', result)) // Then ["Resolved!", "Rejected!"]
  .catch(err => console.log('Catch', err));

Promise.all([a.catch(e => e), b.catch(e => e)])
  .then(result => console.log('Then', result)) // Then ["Resolved!", "Rejected!"]
  .catch(err => console.log('Catch', err));

更进一步,您可以编写一个通用的catch处理程序,如下所示:

const catchHandler = error => ({ payload: error, resolved: false });

那你就可以

> Promise.all([a, b].map(promise => promise.catch(catchHandler))
    .then(results => console.log(results))
    .catch(() => console.log('Promise.all failed'))
< [ 'Resolved!',  { payload: Promise, resolved: false } ]

这样做的问题在于,捕获的值将具有与非捕获的值不同的接口,因此要清理此问题,您可以执行以下操作:

const successHandler = result => ({ payload: result, resolved: true });

现在,您可以执行以下操作:

> Promise.all([a, b].map(result => result.then(successHandler).catch(catchHandler))
    .then(results => console.log(results.filter(result => result.resolved))
    .catch(() => console.log('Promise.all failed'))
< [ 'Resolved!' ]

然后将其保持干燥,您会得到本杰明的答案:

const reflect = promise => promise
  .then(successHandler)
  .catch(catchHander)

现在看起来像什么

> Promise.all([a, b].map(result => result.then(successHandler).catch(catchHandler))
    .then(results => console.log(results.filter(result => result.resolved))
    .catch(() => console.log('Promise.all failed'))
< [ 'Resolved!' ]

第二个解决方案的好处是抽象和DRY。不利的一面是您拥有更多的代码,并且必须记住要体现所有使事情保持一致的承诺。

我将我的解决方案描述为显式和KISS,但确实不够可靠。该界面不能保证您确切知道承诺是成功还是失败。

例如,您可能有以下内容:

const a = Promise.resolve(new Error('Not beaking, just bad'));
const b = Promise.reject(new Error('This actually didnt work'));

这不会被抓住a.catch,所以

> Promise.all([a, b].map(promise => promise.catch(e => e))
    .then(results => console.log(results))
< [ Error, Error ]

没有办法说出哪个是致命的,哪个不是。如果这很重要,那么您将需要实施和接口以跟踪是否成功(reflect确实如此)。

如果您只想优雅地处理错误,则可以将错误视为未定义的值:

> Promise.all([a.catch(() => undefined), b.catch(() => undefined)])
    .then((results) => console.log('Known values: ', results.filter(x => typeof x !== 'undefined')))
< [ 'Resolved!' ]

就我而言,我不需要知道错误或失败的方式,我只是在乎我是否有价值。我将让生成promise的函数担心记录特定错误。

const apiMethod = () => fetch()
  .catch(error => {
    console.log(error.message);
    throw error;
  });

这样,应用程序的其余部分可以根据需要忽略其错误,并在需要时将其视为未定义的值。

我希望我的高级函数能够安全地失败,而不必担心其依赖项失败的原因的细节,并且在必须进行权衡时,我也更喜欢KISS而不是DRY,这最终就是为什么我选择不使用reflect


1
@Benjamin我认为@Nathan的解决方案对于Promises 非常简单和惯用。在reflect提高代码重用性的同时,它还建立了另一个抽象级别。由于Nathan的答案到目前为止只收到了您的一小部分赞成票,我想知道这是否表明他的解决方案有问题,我尚未意识到。

2
@ LUH3417此解决方案从概念上讲不太合理,因为它将错误视为值,并且不会将错误与非错误分开。例如,如果一个承诺合法地解析为可以抛出的值(这是完全可能的),则这将严重破坏。
本杰明·格伦鲍姆

2
@BenjaminGruenbaum因此,例如,new Promise((res, rej) => res(new Error('Legitimate error'))将无法区分new Promise(((res, rej) => rej(new Error('Illegitimate error'))?或更进一步,您将无法过滤依据x.status?我将这一点添加到我的答案中,以便使区别更加明显
Nathan Hagen

3
之所以说这是一个糟糕的主意,是因为它将Promise实现与仅在特定Promise.all()变体中使用过的特定用例相关联,然后Promise消费者也有责任知道特定的承诺不会拒绝,但会吞下它的错误。实际上,reflect()通过调用该方法可以使其“抽象性”更小,更明确PromiseEvery(promises).then(...)。与本杰明的方法相比,上述答案的复杂性应说明这一解决方案。
尼尔

33

在vanilla Javascript中,有一个可以完全实现此功能的功能的最终提案Promise.allSettled已进入第4阶段,已在ES2020中正式认可,并已在所有现代环境中实现。它与其他答案中reflect功能非常相似。这是来自提案页面的示例。在此之前,您必须做以下事情:

function reflect(promise) {
  return promise.then(
    (v) => {
      return { status: 'fulfilled', value: v };
    },
    (error) => {
      return { status: 'rejected', reason: error };
    }
  );
}

const promises = [ fetch('index.html'), fetch('https://does-not-exist/') ];
const results = await Promise.all(promises.map(reflect));
const successfulPromises = results.filter(p => p.status === 'fulfilled');

使用Promise.allSettled代替,上面将等同于:

const promises = [ fetch('index.html'), fetch('https://does-not-exist/') ];
const results = await Promise.allSettled(promises);
const successfulPromises = results.filter(p => p.status === 'fulfilled');

那些使用现代环境的人将可以在没有任何库的情况下使用此方法。在这些情况下,以下代码段应该可以正常运行:

Promise.allSettled([
  Promise.resolve('a'),
  Promise.reject('b')
])
  .then(console.log);

输出:

[
  {
    "status": "fulfilled",
    "value": "a"
  },
  {
    "status": "rejected",
    "reason": "b"
  }
]

对于旧的浏览器,有一个符合规范的填充工具在这里


1
它是第4阶段,预计将于ES2020降落。
Estus Flask,

也可在节点12中使用:)
Callum M

即使其他答案仍然有效,该答案也应该获得更多投票,因为这是解决此问题的最新方法。
雅各布

9

我真的很喜欢本杰明的回答,以及他基本上是如何将所有承诺变成始终解决但有时会因结果而出错的。:)
如果您正在寻找替代品,这是我对您的要求的尝试。此方法只是将错误视为有效结果,并且其编码类似于以下Promise.all方式:

Promise.settle = function(promises) {
  var results = [];
  var done = promises.length;

  return new Promise(function(resolve) {
    function tryResolve(i, v) {
      results[i] = v;
      done = done - 1;
      if (done == 0)
        resolve(results);
    }

    for (var i=0; i<promises.length; i++)
      promises[i].then(tryResolve.bind(null, i), tryResolve.bind(null, i));
    if (done == 0)
      resolve(results);
  });
}

通常称为settle。我们在bluebird中也有这个,我喜欢更好地反映,但这对于将其用于数组的情况是一个可行的解决方案。
本杰明·格林鲍姆

2
好,定居确实是个更好的名字。:)
Kuba Wyrostek

这看起来很像显式promise构造反模式。应该注意的是,您永远不要自己编写这样的函数,而要使用您的库提供的函数(好的,原生ES6有点微不足道)。
Bergi

您能否Promise正确使用构造函数(并避免出现这种情况var resolve)?
Bergi

Bergi,可随时更改答案,但您认为有必要。
库巴·怀罗斯泰克

5
var err;
Promise.all([
    promiseOne().catch(function(error) { err = error;}),
    promiseTwo().catch(function(error) { err = error;})
]).then(function() {
    if (err) {
        throw err;
    }
});

Promise.all会吞噬任何拒绝承诺并存储错误的变量,所以当所有的承诺都得到解决,它将返回。然后,您可以将错误重新抛出,或者执行任何操作。这样,我想您将获得最后一个拒绝而不是第一个拒绝。


1
看起来像这样可以通过将其制成数组并使用来聚合错误err.push(error),因此所有错误都可以冒出来。
ps2goat

4

我遇到了同样的问题,并通过以下方式解决了它:

const fetch = (url) => {
  return node-fetch(url)
    .then(result => result.json())
    .catch((e) => {
      return new Promise((resolve) => setTimeout(() => resolve(fetch(url)), timeout));
    });
};

tasks = [fetch(url1), fetch(url2) ....];

Promise.all(tasks).then(......)

在这种情况下,Promise.all将等待每个Promise都会进入resolvedrejected声明。

有了这种解决方案,我们catch将以一种非阻塞的方式“停止执行”。实际上,我们并没有停止任何事情,我们只是返回Promise处于挂起状态的,Promise在超时后解析后会返回另一个状态。


但这在您运行时会随意调用所有诺言Promise.all。我正在寻找一种方法来侦听所有Promise的调用,但不能自己调用​​它们。谢谢。
SudoPlz

@SudoPlz该方法all()执行此操作,它等待所有Promises的实现或拒绝其中至少一个。
user1016265 '18

是的,但它不仅等待,它实际上调用/启动/启动了该过程。如果您希望在其他地方无法兑现承诺,则应将.all所有内容兑现。
SudoPlz

@SudoPlz希望这会改变您的意见jsfiddle.net/d1z1vey5
user1016265

3
我站得住了。到目前为止,我认为Promises仅在有人调用它们(也称为a then.all调用)时运行,而在它们创建时运行。
SudoPlz

2

这应该与Q的执行方式一致:

if(!Promise.allSettled) {
    Promise.allSettled = function (promises) {
        return Promise.all(promises.map(p => Promise.resolve(p).then(v => ({
            state: 'fulfilled',
            value: v,
        }), r => ({
            state: 'rejected',
            reason: r,
        }))));
    };
}

2

本杰明·格林鲍姆(Benjamin Gruenbaum)的回答当然很棒。但我也可以看到,内森·哈根(Nathan Hagen)的观点与抽象水平似乎很模糊。具有短对象属性e & v也无济于事,但是当然可以更改。

在Javascript中,有一个标准错误对象,称为Error。理想情况下,您总是抛出一个实例/后代。优点是您可以instanceof Error,并且您知道某些错误。

因此,使用这个想法,我来解决这个问题。

基本上捕获错误,如果错误不是错误类型,则将错误包装在错误对象中。结果数组将具有解析值或可以检查的Error对象。

如果您使用某个外部库reject("error")代替,则可以在catch中使用instanceof reject(new Error("error"))

当然,如果您解决了一个错误,您可能会有保证,但是在那种情况下,无论如何都应将它视为错误,就像最后一个示例所示。

这样做的另一个好处是,数组销毁保持简单。

const [value1, value2] = PromiseAllCatch(promises);
if (!(value1 instanceof Error)) console.log(value1);

代替

const [{v: value1, e: error1}, {v: value2, e: error2}] = Promise.all(reflect..
if (!error1) { console.log(value1); }

您可能会说,!error1检查比instanceof简单,但是您也必须破坏两者v & e

function PromiseAllCatch(promises) {
  return Promise.all(promises.map(async m => {
    try {
      return await m;
    } catch(e) {
      if (e instanceof Error) return e;
      return new Error(e);
    }
  }));
}


async function test() {
  const ret = await PromiseAllCatch([
    (async () => "this is fine")(),
    (async () => {throw new Error("oops")})(),
    (async () => "this is ok")(),
    (async () => {throw "Still an error";})(),
    (async () => new Error("resolved Error"))(),
  ]);
  console.log(ret);
  console.log(ret.map(r =>
    r instanceof Error ? "error" : "ok"
    ).join(" : ")); 
}

test();


2

与其拒绝,不如通过一个对象来解决它。当您实现诺言时,您可以执行以下操作

const promise = arg => {
  return new Promise((resolve, reject) => {
      setTimeout(() => {
        try{
          if(arg != 2)
            return resolve({success: true, data: arg});
          else
            throw new Error(arg)
        }catch(e){
          return resolve({success: false, error: e, data: arg})
        }
      }, 1000);
  })
}

Promise.all([1,2,3,4,5].map(e => promise(e))).then(d => console.log(d))


1
这看起来不错,但不优雅,但可以使用
Sunny Tambi

1

我认为以下优惠方式略有不同...比较fn_fast_fail()fn_slow_fail()...虽然后者没有失败,因为这样...你可以检查一个或两个a,并b为实例Error,并throwError如果你把它想达到的catch块(例如if (b instanceof Error) { throw b; })。参见jsfiddle

var p1 = new Promise((resolve, reject) => { 
    setTimeout(() => resolve('p1_delayed_resolvement'), 2000); 
}); 

var p2 = new Promise((resolve, reject) => {
    reject(new Error('p2_immediate_rejection'));
});

var fn_fast_fail = async function () {
    try {
        var [a, b] = await Promise.all([p1, p2]);
        console.log(a); // "p1_delayed_resolvement"
        console.log(b); // "Error: p2_immediate_rejection"
    } catch (err) {
        console.log('ERROR:', err);
    }
}

var fn_slow_fail = async function () {
    try {
        var [a, b] = await Promise.all([
            p1.catch(error => { return error }),
            p2.catch(error => { return error })
        ]);
        console.log(a); // "p1_delayed_resolvement"
        console.log(b); // "Error: p2_immediate_rejection"
    } catch (err) {
        // we don't reach here unless you throw the error from the `try` block
        console.log('ERROR:', err);
    }
}

fn_fast_fail(); // fails immediately
fn_slow_fail(); // waits for delayed promise to resolve

0

这是我的习惯 settledPromiseAll()

const settledPromiseAll = function(promisesArray) {
  var savedError;

  const saveFirstError = function(error) {
    if (!savedError) savedError = error;
  };
  const handleErrors = function(value) {
    return Promise.resolve(value).catch(saveFirstError);
  };
  const allSettled = Promise.all(promisesArray.map(handleErrors));

  return allSettled.then(function(resolvedPromises) {
    if (savedError) throw savedError;
    return resolvedPromises;
  });
};

相比 Promise.all

  • 如果所有的诺言都得到了兑现,它的表现将完全符合标准。

  • 如果一个或多个诺言被拒绝,它将返回第一个被拒绝的诺言,与标准诺言几乎相同,但与等待所有诺言的解决/拒绝不同。

为了勇敢,我们可以改变Promise.all()

(function() {
  var stdAll = Promise.all;

  Promise.all = function(values, wait) {
    if(!wait)
      return stdAll.call(Promise, values);

    return settledPromiseAll(values);
  }
})();

小心。通常,我们永远不会更改内置函数,因为它可能会破坏其他不相关的JS库或与将来对JS标准的更改发生冲突。

My settledPromiseall向后兼容Promise.all并扩展了其功能。

正在开发标准的人-为什么不将其包含在新的Promise标准中?


0

Promise.all使用现代async/await方法

const promise1 = //...
const promise2 = //...

const data = await Promise.all([promise1, promise2])

const dataFromPromise1 = data[0]
const dataFromPromise2 = data[1]

-1

我会做:

var err = [fetch('index.html').then((success) => { return Promise.resolve(success); }).catch((e) => { return Promise.resolve(e); }),
fetch('http://does-not-exist').then((success) => { return Promise.resolve(success); }).catch((e) => { return Promise.resolve(e); })];

Promise.all(err)
.then(function (res) { console.log('success', res) })
.catch(function (err) { console.log('error', err) }) //never executed

-1

您可以通过同步执行程序nsynjs顺序执行逻辑。它将在每个promise上暂停,等待解析/拒绝,然后将resolve的结果分配给data属性,或引发异常(要进行处理,您将需要try / catch块)。这是一个例子:

function synchronousCode() {
    function myFetch(url) {
        try {
            return window.fetch(url).data;
        }
        catch (e) {
            return {status: 'failed:'+e};
        };
    };
    var arr=[
        myFetch("https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"),
        myFetch("https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/NONEXISTANT.js"),
        myFetch("https://ajax.NONEXISTANT123.com/ajax/libs/jquery/2.0.0/NONEXISTANT.js")
    ];
    
    console.log('array is ready:',arr[0].status,arr[1].status,arr[2].status);
};

nsynjs.run(synchronousCode,{},function(){
    console.log('done');
});
<script src="https://rawgit.com/amaksr/nsynjs/master/nsynjs.js"></script>


-1

自ES5以来,我一直在使用以下代码。

Promise.wait = function(promiseQueue){
    if( !Array.isArray(promiseQueue) ){
        return Promise.reject('Given parameter is not an array!');
    }

    if( promiseQueue.length === 0 ){
        return Promise.resolve([]);
    }

    return new Promise((resolve, reject) =>{
        let _pQueue=[], _rQueue=[], _readyCount=false;
        promiseQueue.forEach((_promise, idx) =>{
            // Create a status info object
            _rQueue.push({rejected:false, seq:idx, result:null});
            _pQueue.push(Promise.resolve(_promise));
        });

        _pQueue.forEach((_promise, idx)=>{
            let item = _rQueue[idx];
            _promise.then(
                (result)=>{
                    item.resolved = true;
                    item.result = result;
                },
                (error)=>{
                    item.resolved = false;
                    item.result = error;
                }
            ).then(()=>{
                _readyCount++;

                if ( _rQueue.length === _readyCount ) {
                    let result = true;
                    _rQueue.forEach((item)=>{result=result&&item.resolved;});
                    (result?resolve:reject)(_rQueue);
                }
            });
        });
    });
};

使用签名就像Promise.all。主要区别在于,Promise.wait它将等待所有诺言完成工作。


-1

我知道这个问题有很多答案,而且我敢肯定(如果不是全部)正确。但是,我很难理解这些答案的逻辑/流程。

因此,我查看了上的原始实现Promise.all(),并尝试模仿该逻辑-除了在一个Promise失败的情况下不停止执行之外。

  public promiseExecuteAll(promisesList: Promise<any>[] = []): Promise<{ data: any, isSuccess: boolean }[]>
  {
    let promise: Promise<{ data: any, isSuccess: boolean }[]>;

    if (promisesList.length)
    {
      const result: { data: any, isSuccess: boolean }[] = [];
      let count: number = 0;

      promise = new Promise<{ data: any, isSuccess: boolean }[]>((resolve, reject) =>
      {
        promisesList.forEach((currentPromise: Promise<any>, index: number) =>
        {
          currentPromise.then(
            (data) => // Success
            {
              result[index] = { data, isSuccess: true };
              if (promisesList.length <= ++count) { resolve(result); }
            },
            (data) => // Error
            {
              result[index] = { data, isSuccess: false };
              if (promisesList.length <= ++count) { resolve(result); }
            });
        });
      });
    }
    else
    {
      promise = Promise.resolve([]);
    }

    return promise;
  }

说明:
-循环输入promisesList并执行每个Promise。
-无论Promise是否被解决或拒绝:result根据,将Promise的结果保存在数组中index。还保存解析/拒绝状态(isSuccess)。
-完成所有承诺后,将一个承诺连同其他所有结果一起返回。

使用示例:

const p1 = Promise.resolve("OK");
const p2 = Promise.reject(new Error(":-("));
const p3 = Promise.resolve(1000);

promiseExecuteAll([p1, p2, p3]).then((data) => {
  data.forEach(value => console.log(`${ value.isSuccess ? 'Resolve' : 'Reject' } >> ${ value.data }`));
});

/* Output: 
Resolve >> OK
Reject >> :-(
Resolve >> 1000
*/

2
不要试图重新实现Promise.all自己,有太多事情会出错。例如,您的版本不处理空输入。
Bergi

-4

我不知道您使用的是哪个Promise库,但是大多数都具有allSettled之类的东西

编辑:好的,因为您想使用没有外部库的普通ES6,所以没有这种方法。

换句话说:您必须手动遍历您的诺言,并在所有诺言被兑现后解决新的合并诺言。


我已经编辑了我的问题以澄清-由于ES6带有承诺,因此我想避免使用其他库来实现我认为是基本功能。我想从中获得答案的一个好地方是从一个Promise库中复制源。
内森·哈根
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.