code: function requirejs(deps, callback, errback) {
    if (!Array.isArray(deps)) throw new Error('missing deps array');
    if (callback && typeof callback !== 'function') throw new Error('callback is not a function');
    if (errback && typeof errback !== 'function') throw new Error('errback is not a function');
  
    // return AMD require function or commonjs require function
    function requireFunc() {
      if (typeof arguments[0] === 'string') {
        const dep = arguments[0];
        const got = defined(dep);
        if (got) return got.val;
        throw new Error(`commonjs dependency "${dep}" is not prepared.`);
      }
  
      return requirejs.apply(null, arguments);
    }
  
    requireFunc.toUrl = toUrl;
  
    const depValues = serialResults(deps, d => {
      if (d === 'require') return requireFunc;
      if (d instanceof RegExp) {
        const expanded = [...userSpace.ids(), ...packageSpace.ids()].filter(id => id.match(d));
        return serialResults(expanded, e => userSpace.req(e));
      }
      return userSpace.req(mappedId(d));
    });
  
    const finalize = results => {
      if (callback) return callback.apply(_global, results);
      else return results;
    };
  
    const errHandler = err => {
      if (errback) return errback(err);
      else console.error(err); // eslint-disable-line no-console
    };
  
    if (depValues && typeof depValues.then === 'function') {
      // asynchronous callback
      return depValues.then(finalize, errHandler);
    }
  
    // synchronous callback
    return new Promise(resolve => {
      resolve(finalize(depValues));
    });
  }
docs: AMD require run callback synchronously as much as possible. or use a promise to run callback asynchronous.  returns undefined.  different from requirejs: 1. we don't support optional config. 2. errback only gets one error object.