如何承诺 Cordova 文件插件?

How to promisify Cordova File plugin?

我想在 Apache Cordova 文件插件中承诺一个方法,但我遇到了 'this' 的问题。

最初,我使用的是箭头函数,但当 'this' 问题开始出现时,我删除了箭头函数。

    /**
     * @param {Function} funcToPromisify -
     * @param {*} firstArgForFuncToPromisify -
     * @returns {Promise<any>} -
     */
    const promisifyFunctionOne = function(funcToPromisify, firstArgForFuncToPromisify) {
        return new Promise(function (resolve, reject) {
            funcToPromisify(firstArgForFuncToPromisify, resolve, reject);
        });
    };


    /**
     * @param {Function} funcToPromisify -
     * @returns {Promise<any>} -
     */
    const promisifyFunctionTwo = function(funcToPromisify) {
        return new Promise(function(resolve, reject) {
                funcToPromisify(resolve, reject);
            }
        );
    };


    /**
     * @param {string} pathToFile -
     * @param {Function} urlResolverFunc -
     * @param {object} stateObj -
     * @returns {void} -
     */ 
    const readFile = async function(pathToFile, urlResolverFunc) {
        const fileEntry = await promisifyFunctionOne(urlResolverFunc, pathToFile);  
        console.log(fileEntry); 
        try {
            const fileObj = await promisifyFunctionTwo(fileEntry.file);            
            let reader = new FileReader();        
            reader.onloadend = function() {
                console.log('Successful file read: ' + this.result);            
            };        
            reader.readAsText(fileObj);                    
        }
        catch(error) {        
            console.log(error);
        }
    };

    // Example of how readFile() is being called.
    readFile(pathToFile, window.resolveLocalFileSystemURL);


我希望能够 promisify 函数 FileEntry.file(),但我 尝试此操作时出现此错误:TypeError: this.toInternalURL is not a function at FileEntry.file (FileEntry.js:82)

可在此处查看该代码:https://github.com/apache/cordova-plugin-file/blob/74a46467a081a87bb69b3f2518cbb1db5375028f/www/FileEntry.js#L80

您在定义promisify时使用箭头函数是可以的。这是一个不依赖于上下文的基本示例 (this) -

const promisify = (f) =>
  (...a) => new Promise ((res, rej) => f (...a, res, rej))

const basic = (a, b, c, success, failure) =>
  c === 0
    ? failure (Error("c cannot be zero"))
    : success (a + b + c)

promisify(basic)(1, 2, 3).then(console.log, console.error)
// 6

promisify(basic)(1, 2, 0).then(console.log, console.error)
// Error: "c cannot be zero"

现在对于需要上下文的函数,看我们如何使用 .bind 来保存上下文 -

const promisify = (f) =>
  (...a) => new Promise ((res, rej) => f (...a, res, rej))

const account =
  { balance: 100
  , withdraw: function (amount, success, failure)
    { if (amount > this.balance)
        failure(Error("insufficient funds"))
      else
        (this.balance -= amount, success(this))
    }
  }
  
const withdraw = 
  promisify(account.withdraw.bind(account))
 
withdraw(35).then(console.log, console.error)
// { balance: 65, withdraw: fn... }

withdraw(9999).then(console.log, console.error)
// Error: "insufficient funds"


请注意,这与 node-style promisify 不同,其中异步函数仅采用 one (1) 回调和错误始终作为第一个参数传递给回调 -

const promisify = f =>
  (...a) => new Promise ((res, rej) =>
    f (...a, (e, x) =>
      e ? rej(e) : res(x)
    )
  )
  
const divide = (a, b, nodeCallback) =>
  b === 0
    ? nodeCallback(Error("cannot divide by zero"))
    : nodeCallback(null, a/b)
    
const pdivide =
  promisify(divide)

pdivide(10,2).then(console.log, console.error)
// 5

pdivide(10,0).then(console.log, console.error)
// Error: "cannot divide by zero"

注意,最后一个片段中定义的 promisify 作为 util.promisify

包含在 Node 中