code: func (h *handler) handleBatch(msgs []*jsonrpcMessage) {
  	// Emit error response for empty batches:
  	if len(msgs) == 0 {
  		h.startCallProc(func(cp *callProc) {
  			h.conn.Write(cp.ctx, errorMessage(&invalidRequestError{"empty batch"}))
  		})
  		return
  	}
  
  	// Handle non-call messages first:
  	calls := make([]*jsonrpcMessage, 0, len(msgs))
  	for _, msg := range msgs {
  		if handled := h.handleImmediate(msg); !handled {
  			calls = append(calls, msg)
  		}
  	}
  	if len(calls) == 0 {
  		return
  	}
  	// Process calls on a goroutine because they may block indefinitely:
  	h.startCallProc(func(cp *callProc) {
  		answers := make([]*jsonrpcMessage, 0, len(msgs))
  		for _, msg := range calls {
  			if answer := h.handleCallMsg(cp, msg); answer != nil {
  				answers = append(answers, answer)
  			}
  		}
  		h.addSubscriptions(cp.notifiers)
  		if len(answers) > 0 {
  			h.conn.Write(cp.ctx, answers)
  		}
  		for _, n := range cp.notifiers {
  			n.activate()
  		}
  	})
  }
docs: // handleBatch executes all messages in a batch and returns the responses.