Search code examples
node.jses6-promise

How much is the limit of Promise.all?


Recently i got the following error while resolving a VERY large number of promises:

RangeError: Too many elements passed to Promise.all

I couldn't find any information regarding limits on MDN or ECMA-262.


Solution

  • According to the V8/V8 error code TooManyElementsInPromiseAll of the source code objects Promise

      T(TooManyElementsInPromiseAll, "Too many elements passed to Promise.all")
    

    there is this limit. For the Promise.all i.e. the C++ PromiseAll we have there is a concept of MaximumFunctionContextSlots and kPromiseAllResolveElementCapabilitySlot, here it is the most interesting stuff from the source code:

    // TODO(bmeurer): Move this to a proper context map in contexts.h?
      // Similar to the AwaitContext that we introduced for await closures.
      enum PromiseAllResolveElementContextSlots {
        // Remaining elements count
        kPromiseAllResolveElementRemainingSlot = Context::MIN_CONTEXT_SLOTS,
    
        // Promise capability from Promise.all
        kPromiseAllResolveElementCapabilitySlot,
    
        // Values array from Promise.all
        kPromiseAllResolveElementValuesArraySlot,
    
        kPromiseAllResolveElementLength
      };
    

    I would expect to see a error throw like here

    ThrowTypeError(context, MessageTemplate::TooManyElementsInPromiseAll);
    

    Here it is the code that raise the TooManyElementsInPromiseAll error. Thank to Clarence that pointed me in the right direction!

    BIND(&too_many_elements);
      {
        // If there are too many elements (currently more than 2**21-1), raise a
        // RangeError here (which is caught directly and turned into a rejection)
        // of the resulting promise. We could gracefully handle this case as well
        // and support more than this number of elements by going to a separate
        // function and pass the larger indices via a separate context, but it
        // doesn't seem likely that we need this, and it's unclear how the rest
        // of the system deals with 2**21 live Promises anyways.
        Node* const result =
            CallRuntime(Runtime::kThrowRangeError, native_context,
                        SmiConstant(MessageTemplate::kTooManyElementsInPromiseAll));
        GotoIfException(result, &close_iterator, var_exception);
        Unreachable();
      }
    

    The check of this limit it is here

    // Check if we reached the limit.
        TNode<Smi> const index = var_index.value();
        GotoIf(SmiEqual(index, SmiConstant(PropertyArray::HashField::kMax)),
               &too_many_elements);
    

    so the kMax should solve the clue!