This is the fourth day of my participation in Gwen Challenge
Encapsulate enterprise wechat SDK
Realize multiple picture upload
Iframe redirection + generator solution.
The reason why iframe is used is that to solve the cross-domain problem, the enterprise wechat interface requires the POST method to send messages, so iframe+ POST is directly used to achieve cross-domain (described later).
Why generators? Because generators don’t want to be scoped like a for loop, generators are ones that can be taken from wherever they want. Specific scene:
Since I use the form for cross-domain purposes, when I send a request, the iframe on which the form is located redirects to the request result page, so I need to redirect it back to the current field. So be sure to wait until he is finished, the page jumps, then to redirect back to the current page. Ifame. SRC =”\” SRC =” onload “; submit =” onload “; So if you want to redirect, you have to lock it, otherwise when you redirect back, you’re going to go through onload, and you’re going to keep redirecting, and you’re going to loop.
So that’s the background, so when I redirect the page back, I want to send the next POST request, so I need to check which data I sent, if there’s any more, and if there’s any more, I need to unlock it.
The specific process is as follows:
-
Send a form first
-
Page redirects to request results page
-
After onload, I start to determine if there is a lock
Find it unlocked and redirect to iframe.src=”/”
Locking prevents redirection
-
Determine if there is next data
If so, continue sending as form
-
When sending a form, check whether the form is sent to the last one
Either send the previous data or send it to the last one, or open the lock and allow the page to be redirected back again
You can’t close the lock until the last one is sent
-
. (Repeat the above steps until the data is sent)
In other words, it is not only the onload inside the iframe that needs to determine whether the data has been sent, but also the form that needs to determine whether the data has been sent. If you use the for loop, you have to write the two together, or pass the parameters to determine whether the data has been sent.
Start with a generator:
private* getMsg(msg) {
let i = 0
while (i < msg.length) {
yield msg[i];
i++
}
// The page was redirected the last time it was sent
return "redirect";
}
Copy the code
Cross domain problem solving
Use the form + the iframe
Encapsulate an iframe:
// Prevent iframe redirection recursion
let lock = true
// Control iframe and send data using form
public IframePost(msg, format = "") :Promise<any>{
// Only one iframe is required
let iframe = window.frames["postFrame"]? .frameElement// If it is an array, it is a multi-image upload
this.genMsg = Array.isArray(msg)?this.getMsg(msg):null
if(! iframe){ iframe =document.createElement('iframe')
iframe.style.display = "none";
iframe.name = "postFrame"
iframe.id = "postFrame"
// Listen for the onload event, which is triggered when the page reloads
iframe.addEventListener('load'.() = >{
// The page can be redirected if it is not locked
if(! lock){// Whether to redirect the page
// Redirection process The current page -> submit data after running to the back-end data page -> back-end page onload redirects to the current page
// If not redirected: Stay on the backend data page, you can see the data returned, but cannot send the request again due to cross-domain
iframe.src = "/"
// The redirection must be locked once, otherwise it will cause a redirection loop
lock = true
// If the generator has a value, proceed to the next message
if(this.genMsg){
let nextMsg = this.genMsg.next()
// Use form to send data
// The nextmsg is sent to the last one.! nextMsg.done&&this.FormPost(nextMsg, format)
}
}
})
document.body.appendChild(iframe)
}
if(this.genMsg){
// If it is an array (pictures and files), use the generator to get the send message
return this.FormPost(this.genMsg.next(), format)
}else{
return this.FormPost(msg, format)
}
}
Copy the code
Encapsulate the form:
// Create a form to send data
private FormPost(msg, format = ""){
const form = document.createElement("form");
form.style.display = "none";
// Put the form page in the frame. The advantage of this is that you can retrieve the form directly from Windows without putting it in the iframe
form.target = "postFrame"
form.id = "postForm"
return new Promise((resolve, reject) = > {
form.setAttribute("method"."POST");
// Define the format of the form (message body format)
this.getFormatForm(form, msg, format)
document.body.appendChild(form);
// Submit the form
form.submit();
resolve(form)
}).then((resolve) = >{
// Delete it after submission
form.remove()
// If one more redirection is required, the lock is left unlocked
if(msg.value === "redirect"){
lock = false
}else{
// Do not lock until the end of the sending message
lock = msg.done
}
})
}
Copy the code
-
Send application/ X-www-form-urlencoded format data
The default is this format, so you don’t need to set anything much.
form.setAttribute("action"."http://localhost:3000/efoxPayWechatTips"); let bodyKey = [ { name: "rootKey".value: this.key }, { name: "sendMsg".value: this.genMsg? msg.value:msg } ] bodyKey.forEach((el) = > { var input = document.createElement("input"); input.name = el.name; input.value = JSON.stringify(el.value); form.appendChild(input); }) Copy the code
-
Send formData data
// If you want to send the formData type, assign the input from the page directly to the input of the form form.setAttribute("action"."http://localhost:3000/postFile"); form.setAttribute("enctype"."multipart/form-data") let input = document.createElement("input"); // When formData is used, MSG is actually an input, which is put directly into the form input = msg; form.appendChild(input); let keyInput = document.createElement("input"); keyInput.name = "rootKey" keyInput.value = this.key form.appendChild(keyInput); Copy the code