If you were comfortable with wrapping your code in a  function, you could tag it as async and await the result instead.
Though it's essentially syntactic sugar, async/await provides an easily recognizable chain of events that might be more familiar to someone just learning, but also makes for (arguably) cleaner code.
const opj = [
  { data : {id: 1 , name : "Emad" }},
  { data : {id: 2 , name : "Ahmad" }},
  { data : {id: 3 , name : "Mazen" }}
];
const p = new Promise (resolve => setTimeout(resolve(opj), 300) );
async function getResult() {
  let result = await p;              //wait for p to resolve
  let storData = [...result];        //process the result
  console.log('storData',storData);  //log it
}
getResult();
 
 
As for the "simple explanation", imagine you call a friend on the telephone and ask if he can lend you some sugar. He says "Sure! I'll bring it over to your house right now." This is p. You've kicked off an action somewhere else, but you have no idea how long it will take.
You can keep going about your day, however you can't use the sugar just yet - you have to wait for your friend to arrive (which is what .then( ... ) or await do).
Logging storData outside of .then( ... ) or without an await is the equivalent of hanging up the phone and trying to use the sugar immediately, instead of waiting for your friend to arrive.