Home >WeChat Applet >Mini Program Development >Improve asynchronous encapsulation: handle asynchronous calls with return values - Border City Inn
The last few articles are related to the development of WeChat mini programs, so someone asked: "I don't understand mini programs, can you write something else?".In fact, you don’t need to pay too much attention to the matter of “small program”, because “small program” is just a development scenario in the article. The problems we actually solve are not only encountered in small programs, and the means to solve the problem are completely It has nothing to do with mini programs!
There is a problem left in the asynchronous call of the WeChat applet encapsulated by Proxy:
Like wx.request()
How to encapsulate this situation where there is a return value?
If you need to cancel the request during the request process, the return value of wx.request()
will be used:
const requestTask = wx.request(...); if (...) { // 因为某些原因需要取消这次请求 requestTask.abort(); }
Encapsulated awx. request()
will return a Promise object, which has nothing to do with the original return value of wx.request()
. If you want to be able to cancel the request, you must bring out the original return value of wx.request()
. What should you do?
function wxPromisify(fn) { return async function (args) { return new Promise((resolve, reject) => { const originalResult = fn({ // ^^^^^^^^^^^^^^^^^^^^^^^ // 怎么把 originalResult 带出去? ...(args || {}), success: res => resolve(res), fail: err => reject(err) }); }); }; }
It’s not too fussy, here are several options:
{ promise, originalResult}
or [promise, originalResult]
; awx. request(params, outBox = {})
, assign value to outBox
during processing: outBox.originalResult
; promise.originalResult = ...
. From the user's perspective, most of the time the original return value is not needed. At this time, we definitely want to await awx.request()
instead of deconstructing it first. Then await
(or then()
), so the first method is not optional.
The second method is feasible and can be used directly when the original return value is not needed. But when you need the original return value, it's a little troublesome. You need to generate a container object and pass it in first.
The third method should be the most "unfeeling" to use. In any case, the original value is brought out with the Promise object, use it or not, just feel free to use it!
Now let’s implement the third method and transform wxPromisify()
:
1 I thought it was very simple at first. I originally just return new Promise()
, but now I should just add a temporary variable:
function wxPromisify(fn) { return async function (args) { const promise = new Promise((resolve, reject) => { // ^^^^^^^^^^^^^^^^ promise.originalResult = fn({ // ^^^^^^^^^^^^^^^^^^^^^^^^^ ...(args || {}), success: res => resolve(res), fail: err => reject(err) }); }); return promise; // ^^^^^^^^^^^^^^^ }; }
Then I got an error:
TypeError: Cannot set property 'originalResult' of undefined
This Mistakes are easy to understand and easy to correct...but they are also easy to make!
I originally thought that promise
is a local variable and can be accessed directly, so it is no problem to use it in its sub-scope. But it is ignored here that this subscope is in the constructor. Let’s do a rough analysis:
new Promise()
requires a function (assumed to be called factory
) as a parameter, but the timing of execution of this factory
What is it? Notice that after new Promise()
generates a Promise instance, we do not actively call any method of this instance, so we can conclude that factory
is executed during the construction process. In other words, the Promise instance has not yet been generated at this time, and promise
refers to undefined
.
Now that we know the problem, let’s continue the analysis.
factory
is called during the construction of the Promise instance, and factory
is directly executed in the function body and can be obtained immediately fn
's return value, so after the Promise instance is constructed, the original return value can be obtained. Now let’s modify the code:
function wxPromisify(fn) { return async function (args) { let originalResult; // ^^^^^^^^^^^^^^^^^^^ const promise = new Promise((resolve, reject) => { originalResult = fn({ // ^^^^^^^^^^^^^^ ...(args || {}), success: res => resolve(res), fail: err => reject(err) }); }); promise.originalResult = originalResult; // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ return promise; }; }
We need to assign a value to
promise.originalResult after new Promise()
, and this "value" It is generated in the process of new Promise()
, then just add a local variable originalResult
to bring it out. Done!
Note: The following is an error example!
function wxPromisify(fn) { return async function (args) { let promise = new Promise(); // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ promise = new Promise((resolve, reject) => { // ^^^^^^^^^^ promise.originalResult = fn({ ... }); // ^^^^^^^^^^^^^^^^^^^^^^ }); return promise; }; }
Doing this will not generate theTypeError
mentioned above, but the Promise object obtained from the outside does not carry This time the original return value is brought out using Recommended tutorial: "WeChat Mini Program"originalResult
. The specific reason is the same as the failed attempt above, so I won’t go into details, just a reminder: Two Promise objects are generated here
. 6. Again
wx.request()
as an example. The main purpose of its return value is Provide .abort()
method for canceling requests. This application scenario is actually similar to how Axios handles "Cancellation", so you might as well refer to the method implemented by Axios through cancelToken
. The essence of cancelToken
is the second method mentioned above - passing in the "container" object to bring out the needed things. Bringing it out through a Promise object is essentially the same as bringing it out through a special "container" object, so I won't say more.
The above is the detailed content of Improve asynchronous encapsulation: handle asynchronous calls with return values - Border City Inn. For more information, please follow other related articles on the PHP Chinese website!