避免 js 中承诺冲突的最佳实践

Best practice to avoid clashing promises in js

我的应用程序中有一个可以手动调用的 save 函数和一个每 60 秒运行一次的 autosave 函数。

为了防止两个 ops 试图同时访问同一个文件,我将一个名为 isSaving 的标志设置为 true,当一个开始时 运行,并设置为 false 之后再次。如果 opensave 检测到 autosave 是 运行,它们将等待 1000 毫秒并重试。如果在那之后他们失败了,我认为这是一个错误。

自动保存:

setInterval(autosave, 1000 * 60);
isSaving = false;

function autosave() 
{        
    return new WinJS.Promise(function (complete, error, progress) 
    {
        if(isSaving == false) // no saving op in progress
        {
            // set saving flag on
            isSaving = true;
            // write file
            return writeFile(currentFile)
                .then(function () {
                    // saving flag off
                    isSaving = false;
                    complete();
                });
        }    
        else {
            // silently abort
            complete();
        }        
    });
}

手动保存:

var saveFileAttempts = 0;
function save()
{
    return new WinJS.Promise(function (complete, error, progress)
    {
        if (isSaving == false) // no saving op in progress
        {
            // set saving flag on
            isSaving = true;
            // write file
            return writeFile(currentFile)
                .then(function () {
                    // show notification to user "file saved"
                    return showSaveNotification()
                })
                .then(function () {
                    // set saving flag off
                    isSaving = false;
                    complete();
                });
        }
        else if (saveFileAttempts < 10) { 
            // try again in 1000ms, up to 10 times
            saveFileAttempts++;
            setTimeout(function () { save(); }, 1000);
        }
        else{
            error();
        }
    });
}

打开:

var openFileAttempts = 0;
function open()
{
    return new WinJS.Promise(function (complete, error, progress)
    {
        if (isSaving == false)
        {
            return readFile()
                .then(function (file) {
                    currentFile = file;
                    openFileAttempts = 0;
                    complete();
                });
        }
        else if (openFileAttempts < 10) { 
            // try again in 1000ms, up to 10 times
            openFileAttempts++;
            setTimeout(function () { open(); }, 1000);
        }
        else{
            error();
        }
    });
}

这感觉像是黑客攻击。有没有更好的方法来实现我想要做的事情?

仅供参考:这些函数 return promises 因为还有其他函数调用它们。

如何维护单个承诺链。然后,你可能不需要 setTimeout,这是一个简单的方法,可能有缺陷,没有使用 WinJS,像正常承诺一样编写代码:

setInterval(save, 1000 * 60);
var promise = Promise.resolve(); 



function save(){
    return promise.then(function(){
        return writeFile(currentFile);
    });
}

function open(){
    return promise.then(function(){
        return readFile().then(function (file) {                
            currentFile = file;
        });
    });
}

但我想,此代码的一个问题是,由于它是单一承诺链,您需要在应用程序中正确捕获错误。

与其等待 1000 毫秒再试,我建议使用 promise 来表示保存正在进行以及何时结束。

var saving = null;

setInterval(function() {
    if (!saving) // ignore autosave when already triggered
        save().then(showAutoSafeNotification);
}, 60e3);

function save() {
    if (saving)
        return saving.then(save); // queue
    // else
    var written = writeFile(currentFile);
    saving = written.then(function() {
        saving = null;
    }, function() {
        saving = null;
    });
    return written;
}

你可以对 open 做同样的事情(并且可能想抽象出 written 部分),尽管我看不出它如何干扰(自动)保存。如果您担心在保存文件时读取已经打开的文件,我会让文件系统处理并捕获错误。